I've two classes called FWindow and FFramwWindow. The FFramwWindow class inherits the FWindow. The FWindow class contains two constructor method.
The first one is default constructor and the second one contains one parameter of int type.
I call the second constructor from the FFramwWindow class default constructor to initialize a member variable of the FWindow class called 'value'.
But I don't know why it isn't working -
class FWindow {
public:
int value;
FWindow()
{
this->value = 0;
}
FWindow(int val)
{
this->value = val;
}
};
class FFramwWindow : public FWindow
{
public:
FFramwWindow()
{
FWindow::FWindow(6);
printf("value %d\n", this->value);
}
};
int main(int argc, _TCHAR* argv[])
{
FFramwWindow obj;
return 0;
}
The above code prints - value 0
Where I expected it will print - value 6
Seems it's only calling the default base class constructor, not the second one that I called explicitly.
Note: I'm using Visual Studio 2008
Because you should do the following in constructor:
FFramwWindow() : FWindow(6)
{
....
In your original code you create a local (in constructor scope) object of FWindow.
the code
FWindow::FWindow(6);
is not a call to the parent constructor, but the creation of a local instance of FWindow. The correct syntax in C++ to specify which FWindow constructor should be called is
FFramwWindow() : FWindow(6)
{
...
}
If you do not specify the constructor to use for the base class (and for data members), C++ uses the default constructor, that is
FFramwWindow()
{
...
}
is equivalent to
FFramwWindow() : FWindow()
{
...
}
Note that if you have multiple inheritance you should constructors for each base class separating them with comma. As bonus information, the base constructors are called in the order specified in the inheritance definition, not those in which you specify them in the constructor:
class A {
A();
A(int n);
A(string s);
};
class B {
B(int n = 6);
}
class C {
C();
C(float x);
}
class D: public A, public B, public C {
D();
}
D::D() : C(3),A(5)
{
}
In this example, creating an instance of D will invoke in order the constructors for A(5), B(6), C(3.0), D()
You must call the constructor function of the base class when you declare the derived class's constructor. Consider this example:
#include<iostream>
class base
{
public:
int i;
base()
{
i = 0;
}
base(int p)
{
i = p;
}
};
class derived1: public base
{
public:
derived1():base()
{
std::cout<<i<<std::endl; //i is 0 here
}
};
class derived2: public base
{
public:
derived2():base(10)
{
std::cout<<i<<std::endl; //i is 10 here
}
};
class derived3: public base
{
public:
derived3(int x):base(x)
{
std::cout<<i<<std::endl;
//this takes an argument from the derived class's constructor
//as base class's constructor's parameter
}
};
int main()
{
derived1 d1;
derived2 d2;
derived3 d3(9);
return 0;
}
In derived1 class, the first constructor of the base class is called. In derived2 class, the second constructor is called. And in third case, the constructor function takes an argument which is passed to the base class's constructor (That means we are using the second constructor of base class).
In your code,You didn't call the base class's constructor which by default calls the constructor that takes no argument. That's why it is outputting 0.
FWindow::FWindow(6);
This statement just creates a temporary new object of class FWindow which is destroyed right after this statement is executed. Constructor functions are meant to be called automatically when you create a object. They are not meant to be called manually.
You can find some explanation here: http://www.geeksforgeeks.org/possible-call-constructor-destructor-explicitly/
Related
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.
Is it necessary to call parent constructor with no arguments from child class constructor?
If I have a class A:
class A {
public:
A() : value(100) { }
int get_value() { return value; }
private:
int value;
};
And a class B that inherets from A:
class B : public A {
public:
B() : A() {}
};
Will the constructor of A be called when initializing an object of B even if I do not have: B() : A() {} and the value set to 100?
Will the constructor of A be called when initializing an object of B even if I do not have: B() : A() {} and the value set to 100?
Yes.
Just like a member, if a base sub-object does not have an initialiser, it will be default-initialised. Default initialising A calls the user declared constructor.
You don't even need to declare the contsructor of B. The implicitly generated one does the same thing:
class B : public A {};
I want to create a class constructor which will call it's superclass constructor only on certain condition. My current implementation of this is shown below.
class MyClass : public OtherClass
{
public:
template<typename... Args>
MyClass(bool condition, Args&&... args)
{
if(condition)
{
*(OtherClass*)this = OtherClass(args...);
}
else
{
// Unrelated stuff
}
}
};
I can't use MyClass(...) : OtherClass(...) {} syntax here because superclass's constructor should not be called every time.
Is there any way to call superclass constructor directly instead of calling move constructor (as shown in my example).
You could create 2 different constructors for both the base- and the derived class.
The constructor of the derived class calls the appropriate constructor of the base class.
A static method within the derived class creates an instance based on the passed arguments.
Something like this:
class OtherClass
{
public:
OtherClass()
{
...
}
OtherClass(Args&... args)
{
...
}
} // class OtherClass
class MyClass: public OtherClass
{
private:
MyClass(): OtherClass()
{
...
}
MyClass(Args&... args): OtherClass(args)
{
...
}
public:
static MyClass* createInstance(bool condition,
Args&&... args)
{
if (condition)
return (new MyClass());
else
return (new MyClass(args));
}
} // class MyClass
A solution is to not do this in the constructor, but in a helper function. For example:
class BaseClass {
BaseClass() {}
BaseClass(int x) {setX(x);}
void setX(int x) {
//thing
}
}
class Derived : BaseClass {
Derived(int x) {
if (x>10) setX(x);
}
}
You could overload the constructor in the following way to implement tag dispatching:
struct PassArgs {};
struct DoNotPassArgs {};
class MyClass: public OtherClass {
public:
template<typename... Args>
MyClass(PassArgs, Args&&... args) : OtherClass(args...) {}
template<typename... Args>
MyClass(DoNotPassArgs, Args&&...) : OtherClass() {}
};
Above answer from Robert Kock is not perfectly correct. He is calling Base class (supper class) constructor from initialization list of derived class constructor but without a condition. But as per your question can we call a base class constructor based on a CONDITION from the BODY of derived class constructor?. The answer is NO we can not. As per object oriented principle A Base class constructor must call and initialized first. In the above answer from Robert Kock, base class constructor is called from the initialization list of drive class constructor before control enter inside the body and without any condition. In the initialization list you can not even put any condition. So it is not possible to call a based class constructor to call from the body of a derive class constructor. That is the reason for this kind of requirement we introduce one more method called init() in a class. Now the below example can full fill your requirement. Here in this example you have to add one default constructor in your base class, so that this default constructor call first but in that default constructor you are not going to do anything.
Now see the below example:-
#include<iostream>
class B
{
private:
int x;
int y;
public:
B(){std::cout<<"I am B's default constructor"<<std::endl;}//Default constructor not doing anything
void init(int x)
{
std::cout<<"Based init with param x"<<std::endl;
this->x = x; //this method initializing only one member
y = 0;// just initialized with default value 0
}
void init(int x,int y)
{
std::cout<<"Based init with param x and y"<<std::endl;
this->x = x; // here we initializing all the members
this->y = y;
}
void print()
{
std::cout<<"x ="<<x<<std::endl;
std::cout<<"y ="<<y<<std::endl;
}
};
class D : public B
{
public:
D(int i)
{
std::cout<<"I am D's constructor"<<std::endl;
if( i == 1 )
B::init(3);
else
B::init(4, 5);
}
};
int main()
{
std::cout<<"First Example"<<std::endl;
D *d = new D(1);
d->print();
std::cout<<"Now second Example"<<std::endl;
D *d1 = new D(2);
d1->print();
return 0;
}
I have a question about default constructor on inherited class when the parent one is protected, in my mind the child class will have a default one protected too, but it's not the case.
Is there's a way to force the default constructor to be protected other than force it on child class ?
C++11 - gcc version 5.3.1 20151219 (Debian 5.3.1-4).
int main ( int argc, char ** argv )
{
using namespace std;
class A
{
public:
static std::shared_ptr<A> CreateInstance ()
{
A * pInstance { new A };
return { pInstance, []( A * pInstance )
{
delete pInstance;
}};
};
protected:
A () = default;
~A () = default;
};
class B : public A
{
};
B b; // It's work !
return 0;
}
Thanks for your help,
WCdr
No, a derived class' automatically-generated default constructor will still be public even if the base class constructor is protected.
There are two ways (I can think of) to prevent derived class B from being directly instantiable:
1. Remove the default constructor in class A
This can be accomplished by providing a constructor that takes a dummy argument:
class A
{
public:
// ...
protected:
A (int) {}
};
class B : public A
{
};
B b; // error: B::B()' is implicitly deleted because the
// default definition would be ill-formed
Instantiating B will fail, because B's automatically-generated default constructor will attempt to use A's default constructor, which does not exist.
But this is easily circumvented:
class B : public A
{
public:
B() : A(0) {}
}
B b; // works
2. Force the derived class' constructor to be protected
class B
{
// ...
protected:
B() = default;
}
Option (2) will be the least surprising to others reading your code, and is the option that I recommend. Anyone familiar with static createFoo factory functions will understand why the constructor is made private or protected.
EDIT
When using static create factory functions in a class hierarchy, the common idiom is for derived classes to also provide static create factory functions, and make their constructor private or protected.
Derived classes should not use the create factory function of the base class. They should invoke base class constructor, either implicitly or explicitly.
class Base
{
public:
static shared_ptr<Base> create()
{
return shared_ptr<Base>(new Base);
}
protected:
Base() {...}
};
class Derived
{
public:
static shared_ptr<Derived> create()
{
return shared_ptr<Derived>(new Derived);
}
protected:
Derived() {...} // Implicitly calls base class default constructor
};
// Usage
auto b = Base::create();
auto d = Derived::create();
I am new to c++. When I try to compile the code below , I get this error
constructor for 'child' must explicitly initialize the
base class 'parent' which does not have a default constructor
child::child(int a) {
here is my class
#include<iostream>
using namespace std;
class Parent
{
public :
int x;
Parent(int a);
int getX();
};
Parent::Parent(int a)
{
x = a;
}
int Parent::getX()
{
return x;
}
class Child : public Parent
{
public:
Child(int a);
};
Child::Child(int a)
{
x = a;
}
int main(int n , char *argv[])
{
}
Why I am getting this error ?
How can I resolve it ?
Thanks in advance
The parent class has an explicit constructor, so compiler will not add an implicit 'empty' constructor to it. Additionally your constructor has a parameter, so compiler can not generate an implicit call to it. That's why you must do it explicitly.
This way:
child::child(int a) : parent(a)
{
}
When you initialize an object of a derived class, the base class part has to be constructed first. If you don't initialize it yourself in the derived class' constructor by calling one of its constructors, the compiler will attempt use the default constructor of the base class. In your case the default constructor is not defined because you already provided a custom constructor.
To solve this you will either have to provide a default constructor for the base class or simply call its constructor in the derived class' constructor's initializer list:
child::child(int a) : parent(a)
{
}
At the risk of repeating the error message you got: a child class constructor must invoke its parent's constructor.
The compiler will add an automatic invocation of the parent's default (argumentless) constructor. If the parent does not have a default constructor, you must explicitly invoke one of the constructors it does have by yourself.
The compiler has to enforce this to ensure that the functionality that the child class has inherited from the parent is set up correctly... for example, initialising any private variables that the child has inherited from the parent, but cannot access directly. Even though your class doesn't have this problem, you must still follow the rules.
Here are some examples of constructors in classes using inheritance:
This is fine, ParentA has a default constructor:
class ParentA
{
};
class ChildA
{
public:
ChildA() {}
};
This is not fine; ParentB has no default constructor, so ChildB1 class must explicitly call one of the constructors itself:
class ParentB
{
int m_a;
public:
ParentB(int a) : m_a(a) {}
};
class ChildB1 : public ParentB
{
float m_b;
public:
// You'll get an error like this here:
// "error: no matching function for call to ‘ParentB::ParentB()’"
ChildB1 (float b) : m_b(b) {}
};
This is fine, we're calling ParentB's constructor explicitly:
class ChildB2 : public ParentB
{
float m_b;
public:
ChildB2(int a, float b) : ParentB(a), m_b(b) {}
};
This is fine, ParentC has a default constructor that will be called automatically:
class ParentC
{
int m_a;
public:
ParentC() : m_a(0) {}
ParentC(int a) : m_a(a) {}
};
class ChildC: public ParentC
{
float m_b;
public:
ChildC(float b) : m_b(b) {}
};
Another example where a MyBook class is being derived from the base class Book. Now a custom constructor with two arguments are supplied for the base class constructor, therefore there is no default constructor for the base class. When inside the main function, a derived class object novel is created, at first the compiler will attempt to invoke the base class constructor which does not exist. So, the base class constructor needs to be explicitly called from the derived class constructor to initialize any private variables that the derived class has inherited from the base class but can not access directly (e.g. title string variable). As user rook mentioned, we need follow these rules. You can get more detailed information from the nice explanation of Initialization Lists by Alex Allain. So, Initialization Lists are must required when there is no defined dafault constructor and also for initializing constant members. He summarises-
Before the body of the constructor is run, all of the constructors for
its parent class and then for its fields are invoked. By default, the
no-argument constructors are invoked. Initialization lists allow you
to choose which constructor is called and what arguments that
constructor receives.
#include <iostream>
#include <cstdio>
using namespace std;
class Book {
private:
string title;
protected:
string author;
public:
Book(string t, string a) {
title = t;
author = a;
};
virtual void display() = 0;
};
class MyBook : public Book {
private:
const string className;
protected:
int price;
public:
// Book(t,a) needs to be called before the {} block to initialize, otherwise error (does not match to Book::Book() default constructor will occur)
MyBook(string t, string a, int p) : Book(t, a), className("MyClass"), price(p){
};
void display() {
cout << "Title: " << getTitle() << endl;
cout << "Author: " << author << endl;
cout << "Price: " << price << endl;
};
};
int main() {
string title, author;
int price;
getline(cin, title);
getline(cin, author);
cin >> price;
MyBook novel(title, author, price);
novel.display();
return 0;
}
Hi Just try add default constructor in your parent class (No argument constructor) then compile it. Hope this might resolve your problem.