I believe Constructors and Destructors in base class cannot be inherited by derived classes of the base class. Is my understanding correct.
Your understanding is correct. For example, if you have
class Base
{
Base(int i) {}
};
class Derived: public Base {};
Derived d(3);
This will not compile because the Base constructor is not inherited.
Note that default and copy constructor are created by the compiler if possible, and call the corresponding constructor of base classes, therefore for those constructors it looks as if those were inherited.
I think this is what you are looking for? You can call the superclass constructor by adding the following to your class constructor
SubClass(int foo, int bar)
: SuperClass(foo)
A full example can be found here What are the rules for calling the superclass constructor?
On the contrary, each constructor of a derived class calls a constructor of the base [super-] class. Each destructor of a derived class is called just before the destructor of the base [super-] class.
Inheritance concerns classes, not functions or constructors.
No, they are inherited. Destructors, for one, are always inherited and called in the order reverse to the creation. For example if we have classes foo, bar and xyzzy:
class foo { ... };
class bar : public foo { ... };
class xyzzy : public bar { ... };
Then if you destoy an object of class xyzzy, destructors will be called in the following order: ~xyzzy(), ~bar() and finally ~foo().
Constructors are also always inherited, but they cannot be called directly. You have to use them in the constructor initialization list or the default constructor will be called (default constructor is the one that takes no arguments).For example, say we have following classes:
class foo {
public:
foo();
foo (int _value);
}
class bar : public foo {
int m_value;
public:
bar (int _value);
}
bar::bar (int _value)
{
m_value = _value;
}
In this case, when you create an object of class bar, a constructor for foo is invoked, but it's the default constructor (foo()). Constructor that takes an argument foo (int _value) is never called. But if we changed definition of the bar (int _value) constructor to this:
bar::bar (int _value)
: foo (256 - _value), m_value (_value)
{
}
Then instead of a default constructor, foo (int _value) will be called.
As this question explains, constructors are not inherited. The same applies to destructors.
Related
My derived class should go through the same init procedure as the base class, initializing some vars and setting some states. The following is a simplified example:
class Base
{
protected:
int x = 0;
Base() { x = 1; }
};
class Sub : public Base
{
public:
void printX()
{
printf("%d", x);
}
};
Will the default constructor of my subclass "Sub" call the protected constructor in the base class? This would mean that x in the subclass would be 1 if printed.
EDIT: added return type for printX()
Yes, default constructor is derived class is going to call default constructors of its bases. (It becomes more interesting with virtual inheritance, but there is none in the snippet, so we do not need to go into the horrors of those).
See Implicitly-defined default constructor on https://en.cppreference.com/w/cpp/language/default_constructor for more details:
...That is, it calls the default constructors of the bases and of the
non-static members of this class.
I've searched if constructor exists for an abstract class. I found that the answer is YES, and these constructors can be called or used by derived class objects.
How about user defined constructors for an abstract class??
Can we write or define Default, parametrized or copy constructors for an abstract class??
How about user defined constructors for an abstract class??
Yes,
Can we write or define Default, parametrized or copy constructors for
an abstract class??
Yes
Abstract class cannot instantiate, and since it meant as a base class, you should define a virtual destructor for it.
DEMO: http://coliru.stacked-crooked.com/a/a4b851e70667bb59
It is common to have protected constructors in a base class: they are meant to initialize the private variable of the class. They are called implicitly or explicitly for constructors of derived classes:
default of copy constructors are called implicitly
parameterized constructors must be called explicitly
Example :
class Base {
private int i;
public:
Base(int val) {
i = val;
}
virtual ~Base() { // always a virtual dtor in base class ...
}
// other methods ...
};
class Derived: public Base {
...
public:
Derived(): Base(0) { // explicit call necessary because no default ctor in Base
...
}
...
};
The virtual destructor is recommended because it ensures that if any subclass has a custom destructor it will be called.
I have a Base class that I can't modify the source code. I make a derived class from it and I am trying to make a no-argument constructor for this derived class. The problem is that I can't define the constructor for two reasons:
There is not a non-argument constructor defined for the base class to use it.
I can't pass a default value for the constructor of the base.
class base
{
public:
base (A arg)
{
}
};
class derived : public base
{
public:
derived () : base (arg) //ERROR
{
}
};
Is there a solution to define a non-argument constructor for the derived class?
Cordialement,
Since you cannot change the base class the only option left is to pass an argument to its constructor. You can do this quite easily by constructing a temporary instance of A and passing it to the base class in your ctor initialized list of derived classes.
derived::derived () : base (A())
{
}
In the code above base(A()) will create a temporary instance of A and pass it to the constructor of base.
#include<iostream>
using namespace std;
class base
{
protected:
int a;
public:
base(int i)
{
a=i;
}
};
class derived :protected base
{
public:
derived(){}
void show()
{
cout<<a;
}
};
int main()
{
base obj(2);
derived obj1;
obj1.show();
return 0;
}
Why is this program giving error as In constructor derived::derived():
error: no matching function for call to base::base()
Please explain. As i have read in stackoverflow that in case of inheriting as protected, protected members of base class became protected member of derived class. If I am wrong then please share a good link to clear my misconception
Once you define a constructor for any class, the compiler does not generate the default constructor for that class.
You define the parameterized constructor(base(int i)) for base and hence the compiler does not generate the no argument constructor for base.
Resolution:
You will need to define a constructor taking no arguments for base yourself.
Add this to your base class:
base():a(0)
{
}
EDIT:
Is it needed to define default constructor to every class? Or is it necessary to have the constructor that matches the derived type also present in base type?
The answer to both is NO.
The purpose of constructors in C++ is to initialize the member variables of the class inside the constructor. As you understand the compiler generates the default constructor(constructor which takes no arguments) for every class.
But there is a catch, If you yourself define (any)constructor(one with parameters or without) for your class, the compiler does not generate the default constructor for that anymore. The compiler reasoning here is "Huh, this user writes a constrcutor for his class himself, so probably he needs to do something special in the constructor which I cannot do or understand", armed with this reasoning the compiler just does not generate the default no argument constructor anymore.
Your code above and you assume the presence of the default no argument constructor(When derived class object is created). But since you already defined one constructor for your base class the compiler has applied its reasoning and now it refuses to generate any default argument constructor for your base class. Thus the absence of the no argument constructor in the base class results in the compiler error.
You must give a value to the base constructor:
class Derived : protected base
{
public:
Derived() : base(0)
{
}
};
Depending on your implementation, give the value to the base constructor. However, you may want the Derived constructor to take also int as an argument, and then pass it to the base one.
You need to implement an empty constructor in base or invoke the defined base(int) constructor explicitly from derived c-tor. Without it, when derived c'tor is activated,
it is trying to invoke base() [empty c'tor], and it does not exist, and you get your error.
You haven't defined a default constructor for Base..
When you instantiate an instance of Derived, it will call the Derived() constructor, which will in turn try to call the Base() default constructur which doesn't exist as you haven't defined it.
You can either declare an empty constructor for base Base::Base() or call the existing one as below:
#include<iostream>
using namespace std;
class base
{
protected:
int a;
public:
base(int i)
{
a=i;
}
};
class derived :protected base
{
derived(): Base(123) {} --this will call the Base(int i) constructor)
void show()
{
cout<<a;
}
};
int main()
{
base obj(2);
derived obj1;
obj1.show();
return 0;
}
Lately, I have done much programming in Java. There, you call the class you inherited from with super(). (You all probably know that.)
Now I have a class in C++, which has a default constructor which takes some arguments. Example:
class BaseClass {
public:
BaseClass(char *name); ....
If I inherit the class, it gives me the warning that there is no appropriate default constructor available. So, is there something like super() in C++, or do I have to define a function where I initialize all variables?
You do this in the initializer-list of the constructor of the subclass.
class Foo : public BaseClass {
public:
Foo() : BaseClass("asdf") {}
};
Base-class constructors that take arguments have to be called there before any members are initialized.
In the header file define a base class:
class BaseClass {
public:
BaseClass(params);
};
Then define a derived class as inheriting the BaseClass:
class DerivedClass : public BaseClass {
public:
DerivedClass(params);
};
In the source file define the BaseClass constructor:
BaseClass::BaseClass(params)
{
//Perform BaseClass initialization
}
By default the derived constructor only calls the default base constructor with no parameters; so in this example, the base class constructor is NOT called automatically when the derived constructor is called, but it can be achieved simply by adding the base class constructor syntax after a colon (:). Define a derived constructor that automatically calls its base constructor:
DerivedClass::DerivedClass(params) : BaseClass(params)
{
//This occurs AFTER BaseClass(params) is called first and can
//perform additional initialization for the derived class
}
The BaseClass constructor is called BEFORE the DerivedClass constructor, and the same/different parameters params may be forwarded to the base class if desired. This can be nested for deeper derived classes. The derived constructor must call EXACTLY ONE base constructor. The destructors are AUTOMATICALLY called in the REVERSE order that the constructors were called.
EDIT: There is an exception to this rule if you are inheriting from any virtual classes, typically to achieve multiple inheritance or diamond inheritance. Then you MUST explicitly call the base constructors of all virtual base classes and pass the parameters explicitly, otherwise it will only call their default constructors without any parameters. See: virtual inheritance - skipping constructors
You have to use initiailzers:
class DerivedClass : public BaseClass
{
public:
DerivedClass()
: BaseClass(<insert arguments here>)
{
}
};
This is also how you construct members of your class that don't have constructors (or that you want to initialize). Any members not mentioned will be default initialized. For example:
class DerivedClass : public BaseClass
{
public:
DerivedClass()
: BaseClass(<insert arguments here>)
, nc(<insert arguments here>)
//di will be default initialized.
{
}
private:
NeedsConstructor nc;
CanBeDefaultInit di;
};
The order the members are specified in is irrelevant (though the constructors must come first), but the order that they will be constructed in is in declaration order. So nc will always be constructed before di.
Regarding the alternative to super; you'd in most cases use use the base class either in the initialization list of the derived class, or using the Base::someData syntax when you are doing work elsewhere and the derived class redefines data members.
struct Base
{
Base(char* name) { }
virtual ~Base();
int d;
};
struct Derived : Base
{
Derived() : Base("someString") { }
int d;
void foo() { d = Base::d; }
};
Use the name of the base class in an initializer-list. The initializer-list appears after the constructor signature before the method body and can be used to initialize base classes and members.
class Base
{
public:
Base(char* name)
{
// ...
}
};
class Derived : Base
{
public:
Derived()
: Base("hello")
{
// ...
}
};
Or, a pattern used by some people is to define 'super' or 'base' yourself. Perhaps some of the people who favour this technique are Java developers who are moving to C++.
class Derived : Base
{
public:
typedef Base super;
Derived()
: super("hello")
{
// ...
}
};
There is no super() in C++. You have to call the Base Constructor explicitly by name.