Constructor problems with class inside another class - c++

I think the question title may be impossible to get right but, I have a class (lets call it A) which has a constructor that needs a pointer to another class (called B). This would be fine but when I define a class in a third class (called C), then I get this error after putting a variable into the constructor: error: expected identifier before ‘&’ token, then if I remove the & I get: error: ‘ClassA’ is not a type.
For those who can't understand what I just said (I don't blame you), here is an example:
class A
{
private:
int number;
//etc, etc...
};
class B
{
private:
A* ClassAPntr;
public:
B(A* objectPointer)
{
ClassAPntr = objectPointer;
}
};
class C
{
private:
A ClassA;
B ClassB(&ClassA);
};
int main()
{
C classC;
}

You didn't actually declare a constructor for class C. What you meant to do was this:
class C
{
public:
C()
: b(&a) // you have to provide the arguments to B's constructor here
{ }
private:
A a;
B b; // ... not here
};

Just for clarification, when you did composition by adding A classA private object to class C, the compiler accept this step because A has undefined constructor which means the compiler will make a default constructor for you and call it when make A classA.
The problem in class B because it has a non-default user defined constructor which means that compiler should force you to call it in class C through constructor initialization list or through curly braces in c++11, so it becomes your responsibility simply because compiler can't know which address for which class A Object you are going to pass for class B
constructor.
So why did you get this error message : class A is not a type or expected identifier before ‘&’ token?
the answer is that compiler considered B ClassB(&ClassA) a declaration for a private function with name ClassB and a return value of type B class.
and because you never use this function in your class the compiler will never give you any error related to definition. and you will also never use this member function in other functions like main because it is private
to produce the undefined reference error you can modify c class to be like this:
class C
{
private:
A classA;
B classB();
friend B func() ;
};
B func() {
C c;
return c.classB(); // undefined reference Error
}

Related

Class Pointer reference inside of another Class defined below? (C++ 14, VS 2019)

Problem Summary
I'm attempting to write a series of classes in C++ 14, that are all supposed to be inside of the same class, and have pointer fields that point to object instances of each one of the classes. They are all also supposed to have constructors that assign those fields, using arguments that are pointers to the other class instances. I'm running into a problem where I am unable to call the constructor with the pointer arguments. Below is an illustration of my problem:
Defined in header file:
class A;
class B;
class C;
class A {
public:
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};
Runner code in cpp file:
A::C TEST_C = *new A::C();
A::B TEST_B = *new A::B(&TEST_C);
The line which initializes TEST_B with the constructor pointer argument call gives the following two errors in the VS 2019 compiler:
Error C2664 'A::B::B(C *)': cannot convert argument 1 from 'A::C *' to 'C *'
Error C2512 'A::B': no appropriate default constructor available
My Attempts
The first error line got me thinking that I may need to change my forward class declarations to include their respective parent classes too, as such:
class A;
class A::B;
class A::C;
However, that appears to break the reference to class C completely, and any references to it in the header above it's definition treat it as an undefined reference (Identifier "C" is undefined.). It's as if there were no forward declarations at all.
Adding A:: to each reference to class C in the rest of the header as such:
class A {
public:
class B {
public:
B(A::C* arg) {
ptr = arg;
}
A::C* ptr;
};
class C {
public:
...
};
};
didn't help either, instead the compiler tells me Class "A" has no member "C"..
However, one interesting thing that I did notice, was the fact that if I change the argument being passed to the constructor call for class B, to nullptr, that is:
A::B TEST_B = *new A::B(nullptr);
then the code gets compiled without problems. To me, that meant that this is most likely an issue with my forward class declarations, where the compiler sees that there are classes B and C declared, but it doesn't get to reading the actual content of the classes prior to attempting to reference them.
Is what I'm trying to accomplish here even possible with C++? Is there a way I should be doing this properly, that I'm not seeing?
Thank you in advance for reading my post, any help is appreciated!
The problem is that you've forward declared class C in global namespace instead of class scope A. This means that there are two different class named C one of which is declared to be in the global namespace ::C and the second one as an inner class A::C.
To solve this, just move the forward declaration of class C to inside class scope A as shown below:
header.h
class A {
public:
class C;// forward declaration moved here inside class scope A
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
};
};
Working demo
Also, be careful about other logical bugs like memory leak(if any) in your program.
class A {
public:
class C;
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};

C++: Initialising an object of a parameterized class inside another class

I want to write a C++ program in which an object of a parameterized class A-'a' has to be initialized inside another class B. I should not/can not initialize like 'A a(parameter list);' of class A while declaring the object variable 'a' which is outside the constructor of class B. The necessary parameters to the object 'a' are gotten through the constructor of B. How to initialize 'a' inside B's constructor with the required parameters?
Class A{
public:
A(string s)
{cout<<s;}
};
class B{
private:
A a;
public:
B(string path){
a(path);
}
};
With the above code I am getting errors. How to initialize the object a(path) inside the class B?
The feature you are looking for is member initializer list. In your example it would be used like this:
class B{
B(string path) : a(path) {
}
};

Why can't I have a method with the same name as a member type?

Here is some code that fails in VS2012:
class A;
class B
{
bool A();
A member; // Error: function B::A is not a type name
};
Why doesn't this work? Obviously I'm trying to create a member of type A, not of type B:A() (which isn't a type, as the compiler correctly points out). Is there some way around this without changing the names of either B:A() or class A? Can I explicitly tell the compiler that I want member to be of type class A?
It's possible, you just need to make clear that you want to use the class A:
class A;
class B
{
bool A();
class A member;
};
It fails because they share a namespace. C++ cannot, in general distinguish types and functions based on context (is A() a constructor or a function call). You can make it explicit which one you refer to, e.g.
class A;
class B
{
bool A();
::A member;
};

Member with the same name of the type

I want to create a member function with the same name of the returning type. Example:
class A { };
class B {
public:
A& A() { return *a; }
private:
A* a;
};
However, the compiler won't let me. I tried to change the type of the member return type to ::A (as sugested here, but with no avail. I know I could just change the member name, but I just want to understand why does it has this restriction, and what are my workarounds.
If you declare a member called A you can no longer use the type A without an explicit namespace. You need to change every occurrence of the type A to ::A.
The corrected code looks like:
class A { };
class B {
public:
::A& A() { return *a; }
private:
::A* a;
};
Fixed code on codepad:
http://codepad.org/cilF9rKm
That's because a member with the same name as the class is a constructor. However, you try to declare one with a type, which is an error. You can only define constructors the way the language wants you too (without an explicit return type).
For example, if you had a method in B that said
A x = A();
it is ambiguous whether you are calling B::A() or are constructing a new A object.

C++: newbie initializer list question

Newbie here. I am looking at company code.
It appears that there are NO member variables in class A yet in A's constructor it initializes an object B even though class A does not contain any member variable of type B (or any member variable at all!).
I guess I don't understand it enough to even ask a question...so what's going on here!? My intuition is that you need a variable before you even try to initialize it. How is it possible (or what good does it do) to initialize an object without having the object?
.h:
class A: public B
{
public:
A(bool r = true);
virtual ~A;
private:
}
.cpp:
A::A(bool r) : B(r ? B::someEnumeration : B::anotherEnumeration)
{
}
A::~A()
{
}
Please help.
Thanks,
jbu
Class A (publicly) inherits from class B:
class A: public B
The only way to initialize a base class with parameters is through the initializer list.
This is actually the only way to call the ctor of a base class in C++ as there is noch such thing as super().
class A : public B
{
};
class B
{
public:
int x;
};
A is a derived type from B. Or A inherits B.
So this is valid...
A a;
a.x = 3;
The rest of your code is just calling B's constructor when A is constructed.
class A: public B
{
public:
A(bool r = true); // defaults parameter 1 as "true" if no arguments provided ex A *pA = new A();
virtual ~A;
private:
}
.cpp
A::A(bool r) : B(r ? B::someEnumeration : B::anotherEnumeration)
{
// calls parent class, and initialize argument 1 with some enumeration based on whether r is true or false
}
A::~A()
{
}
Since construtor cannot be inherited so base class data members are to be initialized by passying argument in derived class constructor and with the help of initialization list.
You should also know that in case of polymorphic class initialization of vptr to respective virtual table is done only in constructor.