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.
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.
Related: Does "virtual base class in the case of multilevel inheritance" have significance
I have a template class that can be inherited from in order to impart some select functionality. However, it wants to prevent any classes from further inheriting from anything that inherits it.
The following seems to achieve this:
template<typename Child>
class SealingClass
{
public:
/*public methods etc*/
private:
SealingClass() {}
friend Child;
};
//simplify a bit:
#define Seal( x ) public virtual SealingClass< x >
Now, I can inherit from the above class, as follows:
class NewClass: Seal(NewClass) {};
And if I then try inheriting again from NewClass, as in:
class AnotherClass: public NewClass {};
and then make an instance of said class:
AnotherClass a;
I get the desired error, regarding the constructor in SealingClass being private.
So, everything works as I'd like!
However, I have noticed that if I remove the virtual keyword from the define..
#define Seal( x ) public SealingClass< x >
..my instantiation of AnotherClass now works just fine.
I understand that the virtual keyword, in this context, means that only one instance of the base class is defined in cases of multiple inheritance (eg diamond inheritance) where multiple instances of it could exist, leading to ambiguous function calls etc.
But, why does it affect the functionality of the above?
Thanks :)
If use virtual inheritance, the most-derived type has to do the initialization of this virtual base class. If you don't use virtual inheritance, the directly derived type has to do the initialization.
Therefore, the private ctor does not prevent the derived type NewClass from initializing the direct base class SealingClass, and AnotherClass does not have to initialize NewClass if it's not been virtually inherited.
Some examples:
template<typename Child>
class SealingClass {
public: // for now
SealingClass() {}
};
class NewClass : public SealingClass<T> {
public:
NewClass() : SealingClass<T>() {} // allowed, SealingClass<T> is a
// direct base class
};
class AnotherClass : public NewClass {
public:
AnotherClass() : NewClass() {} // allowed, NewClass is a
// direct base class
AnotherClass() : SealingClass<T>() {} // not allowed, SealingClass<T> is
// no direct nor a virtual base class
};
class NewClass_v : public virtual SealingClass<T> {
public:
NewClass_v() : SealingClass<T>() {} // allowed, SealingClass<T> is a
// direct base class
};
class AnotherClass_v : public NewClass_v {
public:
AnotherClass_v() : NewClass_v() {} // allowed, NewClass_virt is a
// direct base class
AnotherClass_v() : SealingClass<T>() {} // allowed, SealingClass<T> is a
// virtual base class
};
Now, if the ctor of SealingClass is private, AnotherClass_virt is not allowed to call this ctor due to the private access specifier and not being a friend.
If you leave out the explicit initialization of a base class (whether virtual or direct), it is default-initialized ([class.base.init]/8), that is, the default ctor is called implicitly (but you still must have access to the ctor, so it's the same as explicitly writting the call to the default ctor).
Some quotes:
[class.base.init]/1
In the definition of a constructor for a class, initializers for direct and virtual base subobjects and non-static data members can be specified by a ctor-initializer
[class.base.init]/7
A mem-initializer where the mem-initializer-id denotes a virtual base class is ignored during execution of a constructor of any class that is not the most derived class.
[class.base.init]/10
In a non-delegating constructor, initialization proceeds in the following order:
First, and only for the constructor of the most derived class, virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
Emphasis mine.
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.
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.
class AbstractQuery {
virtual bool isCanBeExecuted()=0;
public:
AbstractQuery() {}
virtual bool Execute()=0;
};
class DropTableQuery: public AbstractQuery {
vector< std::pair< string, string> > QueryContent;
QueryValidate qv;
public:
explicit DropTableQuery(const string& qr): AbstractQuery(), qv(qr) {}
bool Execute();
};
Is it necessary to call base contructor in derived class constructor?
No, in fact for it is unnecessary for the base class to have an explicitly defined constructor (though make sure you have a virtual destructor).
So for a typical interface you could have something like this:
class MyInterface {
public:
virtual ~MyInterface() {}
virtual void execute() = 0;
};
EDIT: Here's a reason why you should have a virtual destructor:
MyInterface* iface = GetMeSomeThingThatSupportsInterface();
delete iface; // this is undefined behaviour if MyInterface doesn't have a virtual destructor
It is never obligatory to explicitly call the base class constructor, unless it has parameters. The compiler will call the constructor automatically. Theoretically the base class still has a constructor, but the compiler may optimize it away into non-existence if it doesn't do anything.
No, not in the example you provided. The base class' default constructors will be called automatically in the same order that the base classes are declared, before any member of the derived class is initialized.
If the base class's constructor does not need any parameters, you do not need to call it in the derived class since it is called as a default constructor. However you need to provide a virtual destructor for your base class even if it is empty. Otherwise compiler will generate a default destructor which is non-virtual by default.