Is it necessary to always provide your base class with a constructor? For example if I had the following base class, and then some derived classes.
class Animal
{
public:
//Is this constructor necessary?
Animal();
virtual ~Animal();
};
class Zebra: public Animal
{
public:
Zebra();
~Zebra();
};
class Elephant: public Animal
{
public:
Elephant();
~Elephant();
};
Assuming that I am creating Animal pointers and then dynamically allocating new Zebra and Elephant objects. If I never intend to create an Animal object, then is there any actual need to explicitly create an Animal constructor?
You don't need to explicitly provide constructor.
A default one is generated (if you don't provide other constructor).
so
class Animal
{
public:
virtual ~Animal();
};
is sufficient.
Derived classes constructors would call Base class constructor (explicitly of implicitly).
Related
How can I inherit a constructor from Grandpa(Non-Direct Base) to Son? For example:
class Grandpa
{
public:
Grandpa();
~Grandpa();
};
class Dad : public Grandpa
{
public:
Dad();
~Dad();
};
class Son : public Dad
{
public:
using Grandpa::Grandpa;
~Son();
};
ERROR: "can only inherit constructor from direct base"
There is a way how to make it work?
There is no way to inherit a non-direct base class' constructor. However, you can still use it. If you want to pass a value to Grandpa's constructor from Son's constructor, you can do something like this;
class Grandpa
{
public:
Grandpa(string surname){
// some codes in the constructor
}
~Grandpa();
};
class Dad : public Grandpa
{
public:
Dad(string surname) : Grandpa(surname){};
~Dad();
};
class Son : public Dad
{
public:
Son(string surname) : Dad(surname){};
~Son();
};
Here what we do is simply, passing the value from Son's constructor to Dad's constructor, and it is just propagating to the Grandpa's constructor.
The relation of non virtual inheritance is just as direct and strong as membership: a class constructor absolutely controls the invocation of the constructors of its members and the invocation of the constructors of its direct non virtual bases. When a class is written, the way its members and direct non virtual bases is specified in the source code; changing that could invalidate a fundamental invariant of the class.
Using a non virtual base constructor directly from a further derived class would break the C++ model.
I have a class(names as example):
class Animal
{
public:
// some virtual methods
};
There are also some sub-classes.
class Dog : public Animal
{
public:
Dog(Map&);
// methods - using m_Map
private:
Map& m_Map;
};
class Elephant : public Animal
{
public:
Elephant(Map&);
// methods - using m_Map
private:
Map& m_Map;
};
As you can see, when creating Dog and Elephant objects, Map reference must be provided, and these classes uses it. There are a lot of more similar sub classes of Animal(Dog, Elephant, Mouse, Cat, and more...) - all uses Map object.
All sub-classes of Animal uses Map object, I was thinking about if it would be good idea to add it to Animal class as protected member, for example:
class Animal
{
public:
Animal(Map&);
// some virtual methods
protected:
Map& m_Map;
};
class Dog : public Animal
{
public:
Dog(Map& map) : Animal(map);
// methods - using Animal::m_Map
};
class Elephant : public Animal
{
public:
Elephant(Map& map) : Animal(map);
// methods - using Animal::m_Map
};
However, Animal class will never use Map object, so it seems for me a bit not natural to store it here - for only sub-classes usage.
On the other hand, all sub-classes of Animal will use Map object - so it would be good to indicate it in Animal class. And also I have feeling that code is duplicated when I define it as member in all sub-classes.
What do you think about it? Should Map object be defined as member in all sub-classes, or only in Animal class?
It depends on the semantic links in between animals and maps.
Since you are in C++, then you can use multiple inheritance.
First, implement a MapWrapper class:
class MapWrapper {
private:
Map *theMap;
public:
...
};
and then construct your animals like this:
class Dog : public Animal, private MapWrapper {
};
Note that private inheritance is not generalization/specialization, just a trick to implement some kind of strong composition.
Another possibility is to introduce an intermediate class in between Animal and Dog. Animal is probably a pure abstract class or a contract, so it is probably not fair to modify it for pragmatic purposes. Just introduce an AnimalMap:
class AnimalMap : public Animal {
// everything for the map
};
class Dog : public AnimalMap {
};
If a variable or function is required for all derived types of a base type, then that variable or function should be a part of the base type. This is the very premise of inheritance - de-duplication of code in a logical and systematic manner.
You mentioned that you are struggling with the fact that an Animal object will never actually use a Map. Have you considered a design of your type hierarchy which involves Animal being an abstract class? This means that an Animal would never be instantiated. This makes sense conceptually in the given example - no animal is an animal alone; the category of animal encompasses many other, more specific concepts such as a dog or cat.
I would suggest that this implementation fits your example and resolves your philosophical conundrum.
The map object would be defined in animal class only.why because you are inherit animal class properties for all your sub classes.
it is a advantage , you can create object for animal class ,and you can access the map until you did not have any pure virtual methods in animal class
when it comes to memory size of an object,there is no difference where you are holding the map ,whether in a in a base class or derived class.the size of an derived object will be same only
class animal
{
public:
int animal_id;
int animal_age;
};
class dog :public animal
{
public:
int dog_type_id;
};
int main()
{
dog d1;
animal a1;
cout<<"sizeof d1:"<<sizeof(d1)<<endl;
cout<<"sizeof a1:"<<sizeof(a1)<<endl;
return 0;
}
if i run this code
#include<iostream>
using namespace std;
class Final;
class MakeFinal{
public:
friend class Final;
MakeFinal(){cout<<"makefinal\n";}
};
class Final: public virtual MakeFinal{
public:
Final(){cout<<"Final\n";}
};
class Derived:public Final{
public:
Derived(){cout<<"Derived\n";}
};
int main(){
//Final f;
Derived d;
return 0;
}
Output is :
makefinal
Final
Derived
But if i make MakeFinal() constructor private , compiler shows error message. What is this different constructor call hierarchy based on ?
Refer to:
C++ FAQs - virtual inheritance constructors
http://www.parashift.com/c++-faq/virtual-inheritance-ctors.html
Because of the fact that "Initialization list of most-derived-class's ctor directly invokes the virtual base class's ctor. ", your most derived needs to invoke the constructor of the virtual base directly. Therefore, for what you want to do you'd need to make the most derived class a friend too...
Furthermore, it seems that you don't understand virtual inheritance correctly. Refer to this FAQ to understand the purpose and proper use of virtual inheritance.
If your class A have private constructor, you cannot create object a of this class like that (see):
A a;
When an object b of class B that derives from A is created, base class constructor must also be called. If it is private, it cannot be called and the derived object cannot be created.
I am writing an abstract class that will be a parent for several other classes. I am thinking the copy constructor should be made private because you are using an abstract class and there is nothing to copy. However, I am not a 100% sure.
Am I correct and if I am not why should it be public or protected?
The copy constructor should be private if you do not want objects of the class to be copied. Otherwise, it should be public.
I think protected is the best choice: it leaves the decision on whether or not the object is copyable to the derived classes, while prohibiting the copying at the abstract class level, preventing the dreaded object slicing.
By making the copy constructor private you'll help prevent inadvertent object slicing, where you make a copy of a derived class but lose all the properties of that derived class. The derived classes can make their own copy constructors that are public and do the right thing.
There's one case where the copy constructor should be protected instead of private, when the abstract class has data members. This doesn't happen very often. The base class can copy the base class members while the derived class copies its own members.
class AbstractBase
{
public:
AbstractBase(const std::string &init) : wtf(init) {}
virtual ~AbstractBase() {}
void DoSomething() = 0;
protected:
AbstractBase(const AbstractBase &r) : wtf(r.wtf) {}
const std::string wtf;
};
class Derived : public AbstractBase
{
public:
// ...
Derived(const Derived &r) : AbstractBase(r), moredata(r.moredata) {}
private:
int moredata;
};
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.