C++ - What is this doing if the constructor is private? - c++

In the code below, why does the compiler not complain for mClass2?
class CMyClass{
private:
CMyClass(){}
};
void TestMethod(){
CMyClass mClass1; //Fails.
CMyClass mClass2(); //Works.
}

Because you've just declared a function mClass2 of zero arguments that returns a CMyClass. That's a valid option since there could be, say, a static CMyClass instance which that function has access to. Note that CMyClass still has a public copy constructor.
(To convince yourself, compile this module to assembler and observe that commenting out the line CMyClass mClass2(); produces the same output.)

Because it is declaring a function and not calling the constructor as you think.
This is called as the Most Vexing Parse in c++.
CMyClass mClass2();
declares a function mClass2() which takes no parameter and returns CMyClass

The second one is a function declaration.

People ought to move to the uniform syntax initialization in C++0x/C++11 using the {} brackets instead which removes this issue.
Class C{};
http://www2.research.att.com/~bs/C++0xFAQ.html#uniform-init

Related

Problem in understanding operator overloading

I am reading TCPPPL by Bjarne Stroustrup and I came across the following piece of code (shown below). I have two questions:
Where is the body of the function operator+? I mean there is only the declaration of the function in class X.
What does the line X(int) mean? Is this the constructor with int as a parameter or something else?
class X {
public:
void operator+(int);
X(int);
};
void operator+(X,X);
void operator+(X,double);
void f(X a)
{
a+1; // a.operator+(1)
1+a; // ::operator+(X(1),a)
a+1.0; // ::operator+(a,1.0)
}
1) Where is the body of the function operator+? I mean there is only the declaration of the function in class X.
The definition (body) of operator+ can be anywhere. The code is obviously not a complete program (there is no main). Therefore, the definitions might be below the shown code or even in another compilation unit.
2) What does the line X(int) mean? Is this the constructor with int as a parameter or something else?
This is a declaration of a converting constructor of class X that accepts an integer as an argument.
What does the line X(int) mean?
X(int) is a declaration of a constructor accepting a single integer parameter. Definition is missing.
Where is the body of the function operator+
Wherever you defined it.
This code won't work without the correct definitions.

Issues with declaring classes as part of a class

I'm having an issue writing a class as part of a C++ program - in it I have three classes, FirstClass, SecondClass, and ThirdClass - First and Second classes both include ThirdClass.h, and in SecondClass I can declare them normally, however, in FirstClass the first declaration works fine, but any further declarations give me an error that "ThirdClass is not a type name"
here's a snippet from the class that's erroring
#include "ThirdClass.h"
class FirstClass
{
public:
FirstClass(void);
// This decleration of ThirdClass works fine
FirstClass(ThirdClass ());
FirstClass(const FirstClass& rhs);
~FirstClass(void);
private:
//These are the two that're erroring
ThirdClass nestedClass();
void Init (ThirdClass ());
void Copy (FirstClass);
};
I'm assuming that it's something to do with both of them linking to the same header file, but i've been looking far and wide trying to find a solution online to no avail.
I did manage to get it working by placing the include inside a namespace, but I also read that this was very bad practice so I don't really want to do it that way.
FirstClass(ThirdClass ());
What is this supposed to do?
If the type ThirdClass has been declared then it declares a constructor that takes the address of a function as its argument, that's not what you wanted, right? ThirdClass () is the type of a function that takes no arguments and returns a ThirdClass, so your constructor argument is (the address of) a function of that type.
If ThirdClass hasn't been declared (and the error you're getting implies it hasn't been) then it is equivalent to:
FirstClass ThirdClass();
i.e. a (non-constructor) function called ThirdClass which returns a FirstClass object.
You probably wanted it to be a constructor taking a ThirdClass object as the argument, which would be:
FirstClass(ThirdClass);
Or to avoid copying the argument (which is usually what you want):
FirstClass(const ThirdClass&);
Similarly for your Init function.
The errors saying ThirdClass is not a type name indicate the type hasn't been declared. We can only guess because you didn't show a complete, self-contained example (no cookie for you) but you probably have #include "FirstClass.h" in your ThirdClass.h header, which causes circular reference and only one of the files is processed correctly.
See these questions (and their answers) for more:
cyclic dependency between header files
C++ cyclical header dependency
C++ error: 'Line2' has not been declared
I guess, your constructor and Init() should be
FirstClass(const ThirdClass &rhs);
...
void Init (const ThirdClass &rhs);
Furthermore, you should consider adding include guards.

Anonymous object with one argument cannot be declared

There is this code:
class SomeClass
{
public:
SomeClass(){}
SomeClass(SomeClass& b){}
SomeClass(SomeClass&b, SomeClass& c){}
};
int main()
{
SomeClass a;
SomeClass(); // works all right
//SomeClass(a); error: redeclaration of ‘SomeClass a’
SomeClass(a, a); // works all right
return 0;
}
Anonymous object of SomeClass with 0 and 2 parameters can be declared, however it cannot be declared with only 1 argument. I assume that writing
SomeClass(a);
is the same as
SomeClass a;
How to create anonymous object with one argument?
You can construct a temporary object in a statement of its own with something like:
(SomeClass)a;
or
(SomeClass(a));
As you've observed, the parentheses are needed to resolve the ambiguity between a declaration and an expression statement.
You can create that anonymouse object as the following:
(SomeClass(a));
This resolves the ambiguity since it can't be a declaration of a.
(SomeClass a); // Error: this can't be a declaration because of the parentheses
// but what else should it be?
In that context, the braces are superfluous, which means
SomeClass(a); //declaration of a
is exactly equivalent to
SomeClass a; //declaration of a
which is again equivalent to these:
SomeClass((a))); //declaration of a
SomeClass(((a))); //declaration of a
SomeClass((((a)))); //declaration of a
SomeClass(((((a))))); //declaration of a
All of these declare a variable of name a and type SomeClass.
In general, you avoid the most vexing parse by writing code with the same effect as what you wanted to write, but that can't be parsed as a declaration.
Often, this is done by adding parentheses.
In this case (SomeClass(a)); will do, or (void) SomeClass(a);
Your assumption is correct.
You simply cannot create a temporary object with a single constructor argument in a context where the same statement could be a declaration. The grammar makes it ambiguous (or, it would be ambiguous if the behaviour you're seeing weren't defined to take precedence).
Why not give the object a name, instead?
SomeClass obj(a);
Or, if you have a reason to want the object to be destroyed immediately (sometimes this is useful; e.g. a boost::this_thread::interruption_point, though that takes no arguments), you can still create a temporary but de-ambiguate the statement:
(SomeClass(a)); // the parens prevent this from being a declarative statement
In some scenarios you may also be able to use C-style casts:
(SomeClass)a;
But, hopefully, your SomeClass constructor is actually marked explicit, and we prefer not to use C-style casts anyway.
This problem doesn't arise in other contexts, ones in which a temporary might make more sense anyway:
std::cout << SomeClass(a); // *can't* be a decl of a `SomeClass` called `a`

Passing member function to function pointer

I have to pass in a function pointer of a member function to another class. I couldn't get it to compile and I get the "undefined reference to classB::classB(classA::*)(std::shared_ptr) " error. Can someone help me with this?
Thanks.
classA{
string functionA(share_ptr<int>);
void functionB(){
classB* ptr = new classB(&classA::functionA);
}
}
//in other .h file
classA; //forward declaration
classB{
classB(string (classA::*funcPtr)(shared_ptr<int>); //constructor
}
Your code as I'm writing this:
classA{
string functionA(share_ptr<int>);
void functionB(){
classB* ptr = new classB(&classA::functionA);
}
}
Here:
share_ptr should be shared_ptr.
There is a missing semicolon at the end of the class definition.
Then,
//in other .h file
classA; //forward declaration
classB{
classB(string (classA::*funcPtr)(shared_ptr<int>); //constructor
}
Here:
There are three left parentheses ( but only two right parentheses ).
A semicolon is missing at the end of the class definition.
You're asking about a linking error, but your code should not even compile.
When you state "I couldn't get it to compile" that seems to be correct.
When you then state "I get [undefined reference to...]", well that's a mystery: with the toolchain that you're evidently using, the linker shouldn't be invoked when the compilation fails.
In summary, this question contains some incorrect information and any answer (such as the hypothesis that you haven't defined the function, or the hypothesis that you defined it somewhere but forgot to link in that, or the hypothesis that you're reporting errors from building something else than your code, so on) would be pure guesswork.
Please post a complete small program that compiles and illustrates the linking error.
Cheers & hth.,
Just for giggles, going to answer this even though you said it compiled for you ...
// In a.hpp
#include "b.hpp" // you need to include this because you will not
// be able to call B's constructor in your functionB() method
class A
{
public:
string functionA ( shared_ptr<int> ); // IIRC, needs to be public to call it
// from B's constructor.
// can be public/protected/private depending on where it's called ...
void functionB () {
B * ptrB = new B ( &A::functionA );
}
};
and
// In b.hpp
// Forward declare class A
class A;
// To make the constructor of B cleaner, use a typedef.
typedef string (A::*IntPtrToStrFn) ( shared_ptr<int> );
class B
{
public:
B ( IntPtrToStrFn fnptr );
};
As far as style and code readability goes, this is horrible - ties the two classes together and reaks of code smell. Need to look at some kind of adapter class or other design pattern to get the two classes to work together.
On the surface, this just looks like a forward declaration issue. Try declaring classA::functionB as you've done, and then defining classA::functionB after the definition of classB.

How to get address of member function for local class defined in function (C++)

I am trying to do the following: Obtain the address of a member function from a class that was locally defined within a function.
class ConnectionBase
{
};
template class<EventType, SinkType>
class ConnectionImpl : public ConnectionBase
{
public:
typedef void (SinkType::*EventCallback)(EventType const&);
};
template<class EventType>
class Source
{
template <class SinkType>
boost::shared_ptr<ConnectionBase> setupCallback(typename ConnectionImpl<EventType, SinkType>::EventCallback func, SinkType* sink)
{
// do the actual connecting.
}
};
class SomeClass
{
public:
void someFunction(int const& event){}
}
class SomeUnitTest
{
public:
void someTest()
{
class NestedClass
{
public:
void someFunction(int const& event){}
};
NestedClass nc;
//Try#1 - This does not work
setupCallback<int, NestedClass>(&NestedClass::someFunction, &nc);
//Try #2 - This also does not work
setupCallback<int, NestedClass>(&SomeUnitTest::someTest::NestedClass::someFunction, &nc);
//Try #3 - Following the GCC error output, I tried this
setupCallback<int, NestedClass>(&SomeUnitTest::someTest()::NestedClass::someFunction, &nc);
SomeClass sc;
//This works fine, as expected
setupCallback<int, SomeClass>(&SomeClass::someFunction, &sc);
}
};
Try #2 and #3 utterly confuse GCC, it has no idea what I am trying to do.
Try #1 produces a more helpful error message saying no setupCallback exists that takes the form "setupCallback(void (SomeUnitTest::someTest()::NestedClass::SomeFunction::*), etc)
Which is how try #3 was born.
I can't really find a lot of information about classes defined inside a function, does anyone know the correct syntax for this, and maybe have a resource that discusses this topic?
Ok, it appears this is settled, as both posters have pointed out, local classes have no linkage, it can't work. Now knowing this, I found this article that discusses this, for anyone else that runs into this problem and stumbles across this question: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=420
Edit:
Clarification of setupCallback(), working example with a more regular class
Edit #2:
Updated wording to change "nested" to "local". Added more detail for setupCallback.
Edit #3: Added links to furhter information. Thanks everyone.
I don't know about the syntax problem, the usual access rules should apply - but there is another problem here if that would work as these member functions have no linkage.
To accept local types at all, setupCallback() would have to be a template function - but template type arguments with no linkage are not allowed.
§3.5/8 says:
Names not covered by these rules have
no linkage. Moreover, except as noted,
a name declared in a local scope
(3.3.2) has no linkage.
Members of local classes are not covered there. §9.3/3 clarifies that:
Member functions of a local class
(9.8) have no linkage.
Long story cut short: don't use member functions of a local class as callbacks, use a non-local class instead.
You fist variant is the correct one as long as the specific matter of taking the address is considered. There are no restrictions on taking the address of member functions of local classes. The proper syntax is the usual
&NestedClass::someFunction
ans that's it. You can try saving it in an intermediate pointer in your code
void (NestedClass::*ptr)() = &NestedClass::someFunction;
and I'm sure your compiler will accept it.
However, the problem I suspect exists in your code has absolutely nothing to do with the proper way of taking the address of a member function. It is rather about the way the first parameter of setupCallback is declared. Since you say it works with &SomeClass::someFunction as the first argument, I'd expect setupCallback to be declared as
void setupCallback(void (SomeClass::*cb)(), SomeClass *p); // one possibility
i.e. it is hardcoded to expect a pointer to a member of SomeClass specifically. You cannot supply a pointer to a member of NestedClass instead. NestedClass is completely unrelated to SomeClass and pointers to members of NestedClass are completely incompatible with pointers to members of SomeClass. This is why it won't compile.
Unless there's something you are not showing us (like setupCallback being a function template maybe? Or overloaded for different parameter types?), what you are trying to do is simply impossible to achieve regardless of how you take the member address, as long as NestedClass remains unrelated to SomeClass. Function setupCallback is designed to work with SomeClass and SomeClass only.
Provide more information about setupCallback. How is it declared?
Note that if the setupCallback is declared as a function template parametrized by class type, as in
template <class T> void setupCallback(void (T::*cb)(), T* p);
then you won't be able to use the local class NestedClass as template argument for parameter T. In this case the fact that your NestedClass has no linkage does indeed come into play. But, again, it has nothing to do with taking the member address, but rather caused by the fact that classes with no linkage cannot be used as template arguments in C++.