LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-28-2020, 12:29 AM   #1
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 197

Rep: Reputation: 31
C++ constructor


It sounds simple enough when trying to open a file or to test the existence of a file.

Code:
{
  std::ifstream f("filename");
  if (f) {
    // file exists
  }
}
My question is, what is f when "filename" does not exist? To do the same in my own classes, how to write the constructor that returns that "null" object?
 
Old 06-28-2020, 12:42 AM   #2
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 298

Rep: Reputation: Disabled
That shouldn't compile. f isn't something that can be implicitly converted to a boolean. To be a NULL object it would have to be a pointer of sometype (in modern c++ a nullptr). To test the f object you can use the state functions (i.e. good, bad, fail). A constructor can't return a null object.
 
Old 06-28-2020, 01:08 AM   #3
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 371

Rep: Reputation: 165Reputation: 165
There is nothing wrong with writing C in a C++ program:

Code:
FILE *fp;
fp=fopen ("filename", "r");
if (fp) {
  // file exists
}
Ed
 
1 members found this post helpful.
Old 06-28-2020, 01:13 AM   #4
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 197

Original Poster
Rep: Reputation: 31
It does compile. I used this technique to do quick checks for flag file all the time.

After some "stepping into", I see 'f' returned is a valid object when "filename" does not exist. That leaves me wonder why the statement "if (f) {}" will work. My closest attempt is this:

Code:
#include <iostream>
#include <fstream>

int main()
{
	std::ifstream iF("foo");
	if (iF) {
		std::cerr << "foo exists.\n";
	}
	else {
		std::cerr << "foo not exists.\n";
	}

	class MyClass {
	public:
		operator bool() { return false; } // sucks
	};

	MyClass c;
	if (c) {
		std::cerr << "c valid.\n";
	}
	else {
		std::cerr << "c not valid.\n";
	}
}
 
Old 06-28-2020, 01:16 AM   #5
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 197

Original Poster
Rep: Reputation: 31
Quote:
Originally Posted by EdGr View Post
There is nothing wrong with writing C in a C++ program:
Thanks. But my point is how to implement your own classes to enjoy the benefit of this construct:
Code:
MyClass c;
if (c) {
  // I'm good to go.
}
else {
  // No go, get help.
}
I don't want to throw exception.
 
Old 06-28-2020, 01:30 AM   #6
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 371

Rep: Reputation: 165Reputation: 165
Quote:
Originally Posted by Jerry Mcguire View Post
Thanks. But my point is how to implement your own classes to enjoy the benefit of this construct:
Code:
MyClass c;
if (c) {
  // I'm good to go.
}
else {
  // No go, get help.
}
I don't want to throw exception.
As SoftSprocket said, the constructor cannot fail. "c" will never be NULL. You need to create and test a member function like c->success ().

IMO, this is much more convoluted than the C method.

ETA: My comment assumed "c" was declared as a pointer to MyClass and allocated with new.
Ed

Last edited by EdGr; 06-28-2020 at 02:00 AM.
 
Old 06-28-2020, 06:20 AM   #7
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 197

Original Poster
Rep: Reputation: 31
No it is not solved.

Code:
  std::ifstream f("filename");
  if (f) { // <--
  }
Could any one help us understanding how does the if-clause interpret (f) at the <-- statement.
 
Old 06-28-2020, 08:57 AM   #8
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 298

Rep: Reputation: Disabled
Well, some where I missed this. fstream overloads the !operator so that !f is a synonym for fail https://en.cppreference.com/w/cpp/io..._ios/operator!
 
Old 06-28-2020, 09:05 AM   #9
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 14,618

Rep: Reputation: 4755Reputation: 4755Reputation: 4755Reputation: 4755Reputation: 4755Reputation: 4755Reputation: 4755Reputation: 4755Reputation: 4755Reputation: 4755Reputation: 4755
I think that was already explained.
std::ifstream f(<anything>) is a constructor which will create a c++ object named f. Probably usable, but probably useless. Anyway, the class is created.
if (anything) is interpreted quite easily: anything is converted to a number (if that was not a number already). f is a non-null object, therefore it will be converted to a non-zero number. Finally if will check if that number (result) was non-zero (in your case it is most probably the pointer to the class instance).

http://www.cplusplus.com/reference/f...tream/is_open/
 
Old 06-28-2020, 09:50 AM   #10
EdGr
Member
 
Registered: Dec 2010
Location: California, USA
Distribution: I run my own OS
Posts: 371

Rep: Reputation: 165Reputation: 165
"bool" is being overloaded. The function call is implied. http://www.cplusplus.com/reference/i.../operator_bool

IMO, overloading is a terrible feature. A reader can't look at code and figure out what it does without also looking at a bunch of declarations. It is much better to explicitly call the appropriate function.
Ed

Last edited by EdGr; 06-28-2020 at 10:05 AM.
 
Old 06-28-2020, 10:01 AM   #11
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 298

Rep: Reputation: Disabled
Actually, it's not a pointer , it's a class object and it can't be converted to a number but since the !operator (and bool operator) is overloaded you can test it with a bool operation.
i.e.
Code:
class A {
	public:
		operator bool () {
			return true;
		}

		bool operator! () {
			return false;
		}

};
 
Old 06-28-2020, 11:06 AM   #12
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 197

Original Poster
Rep: Reputation: 31
Then it's no magic. Just operator bool().

Code:
{
	class MyClass {
	public:
		MyClass(const std::string& filename)
			: iF(filename)
		{
		}
		std::ifstream iF;
		explicit operator bool() const { return static_cast<bool>(iF); } // <-- Ha!
	};

	MyClass c( "foo" );
	if (c) {
		std::cerr << "foo valid.\n";
	}
	else {
		std::cerr << "foo not valid.\n";
	}
}
Thanks.
 
Old 06-28-2020, 10:09 PM   #13
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 9,597

Rep: Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278
After a quick trip to http://www.cplusplus.com/reference/f...ream/ifstream/

Code:
#include <iostream>
#include <fstream>

int main()
{
  using namespace std;
  ifstream f("nonexistent");
  cout << f.fail() << "\n";
  return 0;
}
That prints "1".
 
Old 06-28-2020, 10:17 PM   #14
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 9,597

Rep: Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278Reputation: 4278
Quote:
Originally Posted by Jerry Mcguire View Post
It sounds simple enough when trying to open a file or to test the existence of a file.

Code:
{
  std::ifstream f("filename");
  if (f) {
    // file exists
  }
}
My question is, what is f when "filename" does not exist? To do the same in my own classes, how to write the constructor that returns that "null" object?
I'm sorry, what am I reading here?

There is absolutely nothing wrong with the way you're checking for the file's existence.

Obviously, if you also want to handle the file not existing, you'd extend the code to:

Code:
{
  std::ifstream f("filename");
  if (f) {
    // file exists
  } else {
    // file does not exist
  }
}
I assume you already knew that.

And as for this:

Code:
how to write the constructor that returns that "null" object?
Quote:
Originally Posted by Jerry Mcguire View Post
Thanks. But my point is how to implement your own classes to enjoy the benefit of this construct:
Code:
MyClass c;
if (c) {
  // I'm good to go.
}
else {
  // No go, get help.
}
I don't want to throw exception.
Well, there are some options...

Obviously, it is impossible for the constructor to ever return nullptr. That's not how constructors work.

You said "null object", and that actually is a pattern that you can use to solve this. https://en.wikipedia.org/wiki/Null_object_pattern#C++

Another option is to have a state variable on the class that determines whether or not the file exists. That's the pattern for Qt code, which does not use exception handling.

If you want the correct suggestion, then it actually is "throw an exception".

https://isocpp.org/wiki/faq/exceptions#ctors-can-throw

Last edited by dugan; 06-28-2020 at 10:33 PM.
 
Old 06-28-2020, 11:28 PM   #15
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,051

Rep: Reputation: 1469Reputation: 1469Reputation: 1469Reputation: 1469Reputation: 1469Reputation: 1469Reputation: 1469Reputation: 1469Reputation: 1469Reputation: 1469
(It is hard to follow 'the standard C++ ways' as C++ is an union of many different concepts. That's why some contructors throw exceptions, others create a 'marked as broken' object.
IMHO Yossi Kreinin's C++ FQA is a mandatory reading for a beginner.)

Last edited by NevemTeve; 06-29-2020 at 01:07 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Constructor takes string => constructor not called...? (C++) JohnGraham Programming 4 02-16-2012 12:37 PM
C++ constructor/copy constructor issues in g++ 3.4.6 abhinav.dube15 Programming 7 03-13-2011 08:27 AM
Class constructor not being called ChimpFace9000 Programming 1 06-03-2002 08:54 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:05 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration