I have a problem with instantiating a class as a member of another class.
Here is my code:
class myClassA{
public:
myClassA(){
printf("myClassTwo ctor");
}
void doSomething(){ printf("myClassA did something\r\n");}
};
class myClassB{
public:
myClassB(int i){
printf("myClassA ctor got %d\r\n",i);
threeMyI = i;
}
private:
int threeMyI;
};
class myClassC{
public:
myClassC(){
printf("C ctor without params\r\n");
}
myClassA instanceA;
myClassB instanceB(29); //<== Not working why??
};
I have a class myClassC which I want to have two members, one of type myClassA and one myClassB. This works well for myClassA. But as soon as I try to create an instance of myClassB, which has an ctor parameter, it fails with the following compiler error:
..\src\main.cpp:34:21: error: expected identifier before numeric constant
myClassB instanceB(29); //<== Not working why??
..\src\main.cpp:34:21: error: expected ',' or '...' before numeric constant
In my main function this type of declaration works well:
int main(void){
printf("class test\r\n");
myClassC instanceC1;
myClassA instanceA1;
myClassB instanceB1(25);
return 0;
}
But I have no idea what makes the big difference when instantiating a class with ctor parameters. Hope somebody can give me an hint what I'm doing wrong.
You can only declare member variables, you cannot instantiate them.
To invoke the constructor of a member-variable you can use the memberwise initialization paradigm in your own constructors:
struct A { // same as class A but public by default
int m_a;
A(int a) : m_a(a) {}
};
struct B {
A m_a;
int m_b;
B(int a, int b) : m_a(a), m_b(b) {}
};
Or using your code:
#include <cstdio>
class myClassA{
public:
myClassA(){
printf("myClassTwo ctor");
}
void doSomething(){ printf("myClassA did something\r\n");}
};
class myClassB{
public:
myClassB(int i) : threeMyI(i) {
printf("myClassA ctor got %d\r\n",i);
}
private:
int threeMyI;
};
class myClassC{
public:
myClassC() : instanceA(), instanceB(20) {
printf("C ctor without params\r\n");
}
myClassA instanceA;
myClassB instanceB;
};
int main()
{
myClassA a;
myClassB b(10);
myClassC c;
}
Live demo
From what I have understand, it seems that you want to use a default instantiation for your private attribute instanceB. In that case, what you are proposing is not legal, default input parameters should be set as followed
myClassC() : instanceB(29) { // mind the ":" character
printf("C ctor without params\r\n");
}
This will have the effect to call the constructor of myClassB to instantiate your private attribute instanceB with relevant default parameter.
Related
Why does this code:
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
};
int main(void)
{
B *b = new B(5);
delete b;
}
Result in these errors:
main.cpp: In function ‘int main()’:
main.cpp:13: error: no matching function for call to ‘B::B(int)’
main.cpp:8: note: candidates are: B::B()
main.cpp:8: note: B::B(const B&)
Shouldn't B inherit A's constructor?
(this is using gcc)
If your compiler supports C++11 standard, there is a constructor inheritance using using (pun intended). For more see Wikipedia C++11 article. You write:
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
using A::A;
};
This is all or nothing - you cannot inherit only some constructors, if you write this, you inherit all of them. To inherit only selected ones you need to write the individual constructors manually and call the base constructor as needed from them.
Historically constructors could not be inherited in the C++03 standard. You needed to inherit them manually one by one by calling base implementation on your own.
For templated base classes, refer to this example:
using std::vector;
template<class T>
class my_vector : public vector<T> {
public:
using vector<T>::vector; ///Takes all vector's constructors
/* */
};
Constructors are not inherited. They are called implicitly or explicitly by the child constructor.
The compiler creates a default constructor (one with no arguments) and a default copy constructor (one with an argument which is a reference to the same type). But if you want a constructor that will accept an int, you have to define it explicitly.
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
public:
explicit B(int x) : A(x) { }
};
UPDATE: In C++11, constructors can be inherited. See Suma's answer for details.
This is straight from Bjarne Stroustrup's page:
If you so choose, you can still shoot yourself in the foot by inheriting constructors in a derived class in which you define new member variables needing initialization:
struct B1 {
B1(int) { }
};
struct D1 : B1 {
using B1::B1; // implicitly declares D1(int)
int x;
};
void test()
{
D1 d(6); // Oops: d.x is not initialized
D1 e; // error: D1 has no default constructor
}
note that using another great C++11 feature (member initialization):
int x = 77;
instead of
int x;
would solve the issue
You have to explicitly define the constructor in B and explicitly call the constructor for the parent.
B(int x) : A(x) { }
or
B() : A(5) { }
How about using a template function to bind all constructors?
template <class... T> Derived(T... t) : Base(t...) {}
Correct Code is
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
public:
B(int a):A(a){
}
};
main()
{
B *b = new B(5);
delete b;
}
Error is b/c Class B has not parameter constructor and second it should have base class initializer to call the constructor of Base Class parameter constructor
Here is how I make the derived classes "inherit" all the parent's constructors. I find this is the most straightforward way, since it simply passes all the arguments to the constructor of the parent class.
class Derived : public Parent {
public:
template <typename... Args>
Derived(Args&&... args) : Parent(std::forward<Args>(args)...)
{
}
};
Or if you would like to have a nice macro:
#define PARENT_CONSTRUCTOR(DERIVED, PARENT) \
template<typename... Args> \
DERIVED(Args&&... args) : PARENT(std::forward<Args>(args)...)
class Derived : public Parent
{
public:
PARENT_CONSTRUCTOR(Derived, Parent)
{
}
};
derived class inherits all the members(fields and methods) of the base class, but derived class cannot inherit the constructor of the base class because the constructors are not the members of the class. Instead of inheriting the constructors by the derived class, it only allowed to invoke the constructor of the base class
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
B(int x):A(x);
};
int main(void)
{
B *b = new B(5);
delete b;
}
I know it's OK to call base class function in a derived class constructor, because base class is constructed before derived class.But I'm not sure if this is a good practice.Example code is:
class Base {
public:
int Get() const { return i_; }
void Set(const int i) { i_ = i; }
private:
int i_{0};
};
class Derived : public Base {
// initialize `derived_i_` with a call to base class function, Is this a good
// practice in production code?
Derived() : derived_i_{Get()} {
// do some other things
}
private:
int derived_i_{0};
};
To be more pedantic, you could write your constructor as the following:
Derived() : Base(), derived_i_{Get()} {
// do some other things
}
The compiler should fully construct the base class before doing any initialization of the derived class.
I have the following situation:
Factory class implementation:
class FactoryClassA {
public:
FactoryClassA(){};
~FactoryClassA(){};
ClassA create(double a, double b) {
return ClassA;
};
};
ClassA implementation:
class ClassA {
friend class FactoryClassA
~FactoryClassA() {}
private:
ClassA(double a = 0, double b = 0)
{
a(a),
b(b)
};
double a;
double b;
};
OtherClass implementation:
class OtherClass {
public:
OtherClass() {
ClassFactory myClassAFactory;
aClassA = myClassAFactory.create();
}
~OtherClass() {};
private:
aClassA;
};
Unfortunately, this does not work. Because in the (empty) member initializer list of OtherClass, the empty constructor of ClassA is called, which does not exist.
The reason why I made the constructor of ClassA private, is that I want the user to only create objects of ClassA through the FactoryClassA.
First of all, create() should have a return type:
ClassA create(double a, double b) {
return {a, b};
}
I am not going through all the other syntactic bugs. Please fix them, because others might find your question when they search for answers. Please make it easy for them to understand your question.
This has to be in your code after ClassA has been defined, because the compiler has to know the size of a ClassA object as well as the constructor to use.
Second, just initialize your members before the constructor body:
OtherClass() :
aClassA{ClassFactory{}.create(0.0, 0.0)}
{}
You might prefer to have create() as a static member function of ClassFactory. Then the OtherClass constructor looks like this:
OtherClass() :
aClassA{ClassFactory::create(0.0, 0.0)}
{}
That is more intuitive.
This code is full of small errors, that make it unuseable. First syntax for member initialization for a class is :
class A {
A(x, y): m_a(x) { ... }
...
}
and class declaration are statements so they need the final ;
Next, the dtor for a class must be public if you want to be able to use temporary objects.
The default values should not be in ClassA ctor but on create factory method.
Finally, you should use a static factory in OtherClass, no need to create a new factory for each object.
Code becomes:
class FactoryClassA;
class ClassA {
public:
friend class FactoryClassA;
~ClassA(){}
private:
ClassA(double a, double b):a(a),b(b){}
double a;
double b;
};
class FactoryClassA {
public:
FactoryClassA(){}
~FactoryClassA(){}
ClassA create(double a = 0, double b = 0) {
return ClassA(a, b);
}
};
class OtherClass {
public:
OtherClass(): aClassA(myClassAFactory.create()){}
~OtherClass(){}
private:
static FactoryClassA myClassAFactory;
ClassA aClassA;
};
FactoryClassA OtherClass::myClassAFactory;
Not far from original one, but this ones compiles...
I'm trying to set up a copy constructor and i'm getting this error
class Class1{
public:
int get_data();
void set_data(int);
private:
int d;
};
int Class1::get_data(){
return d;
}
void Class1::set_data(int data){
d = data;
}
class Class2 : public Class1{
Class2(const Class2&);
};
Class2::Class2(const Class2 &c2) : Class1(){
set_data(c2.set_data());
}
whats a solution to this problem. i read some of the previous questions and i understand why this is happening. but making set_data() const is not an option.
whats the accepted approach for copy constructors?
thanks,
You could just write a constructor for Class1 taking an int parameter:
class Class1 {
explicit Class1 (int i) : d (i) {}
// as before
};
class Class2 : public Class1 {
Class2 (Class2 const & c2) : Class1 (c2.get_data ()) {}
};
However, the default copy constructor should be enought here (i.e. you don't need to write your own, the compiler will do it for you).
Generally speaking, you should use initialisation lists:
http://www.parashift.com/c++-faq-lite/ctors.html
in the constructors (read the whole entry in the faq)
Edit: You forgot the 'const' qualifier for your get_data function.
Don't you want:
set_data(c2.get_data());
(and make the Class1::get_data() member function const)?
But you really should be using constructor initialization lists:
Class2::Class2(const Class2 &c2)
: Class1(c2)
{
}
This code uses the compiler-generated default copy constructor for Class1. In many cases you shouldn't use the default copy constructor or copy-assign operator overload, but here it's fine because the sole data member of Class1 is an int object.
In fact, you could even rely on the compiler-generated default copy constructor for Class2.
EDIT: Here is some example code:
#include <iostream>
class Class1{
public:
Class1() : d(0) { } // Provide a no-arg constructor to initialize `d`
int get_data() const; // Class1::get_data() is `const` because it does not change the `Class1` object.
void set_data(int);
private:
int d;
};
int Class1::get_data() const{
return d;
}
void Class1::set_data(int data){
d = data;
}
class Class2 : public Class1{
public:
Class2();
};
Class2::Class2()
: Class1()
{
}
int main() {
Class2 other_c2;
other_c2.set_data(14);
Class2 c2(other_c2);
std::cout << c2.get_data() << '\n';
}
http://codepad.org/jlplTYrH
Why I can't access base class A's a member in class B initialization list?
class A
{
public:
explicit A(int a1):a(a1)
{
}
explicit A()
{
}
public:
int a;
public:
virtual int GetA()
{
return a;
}
};
class B : public A
{
public:
explicit B(int a1):a(a1) // wrong!, I have to write a = a1 in {}. or use A(a1)
{
}
int GetA()
{
return a+1;
}
};
class C : public A
{
public:
explicit C(int a1):a(a1)
{
}
int GetA()
{
return a-1;
}
};
A's constructor runs before B's, and, implicitly or explicitly, the former construct all of A's instance, including the a member. Therefore B cannot use a constructor on a, because that field is already constructed. The notation you're trying to use indicates exactly to use a constructor on a, and at that point it's just impossible.
To build on Alex' answer, you can initialize the base class' "a" member by controlling its construction, like so:
class B : public A
{
public:
explicit B(int a1) : A(a1) { } // This initializes your inherited "a"
...
};
Note that I'm constructing the base class (capital "A") above, rather than attempting to directly initialize its inherited member (lowercase "a", drawing from your example).
To build even further on pilcrow's answer, you could easily initialize the A member like you want by overriding it in your B class:
class B : public A
{
public:
int a; // override a
explicit B(int a1) : a(a1) // works now
{
}
...
};
Though, I wouldn't necessarily recommend this ;)