When working with inheritance and abstract base classes, if your base class has a function that is purely virtual virtual void doSomething() = 0;
, this means that every class that inherits from this base class must implement this function; also, this base class can not be instantiated since it will be abstract.
When working with constructors for public, protected & private member access will restrict how the class behaves to outside callers. If the constructor is public, then that constructor can be called and an instance of that object can be created, provided the class is not abstract. When a constructor is protected, you can not call the constructor from outside of the class; however, any class that inherits from it can call the protected constructor, unless a friend modifier is used.
This is what it means to be abstract. A base class that is abstract can not be an object, but is an encapsulated concept or idea that contains all of the information that is common between all derived classes. It is a sub-object to an object that can be instantiated.
If you are using a purely virtual method as in this example then the base class can not be instantiated, however if you are using just virtual methods and no purely virtual methods then yes it can be instantiated! But be careful with virtual methods in a base class and calling them within the constructor, they can be dangerous.
I will show a simple sample of an abstract base class with both public & protected constructors. The first case will be with a public constructor:
class Animal {
public:
enum AnimalType {
AMPHIBIAN,
BIRD,
FISH,
MAMMAL,
REPTILE,
}; // AnimalType
protected:
AnimalType m_type;
int m_age;
float m_weight;
std::string m_strVoice;
public:
Animal( AnimalType type, int age, float weight ) :
m_type( type ), m_age( age ), m_weight( weight )
{}
virtual ~Animal() {} // Virtual Due To Inheritance
AnimalType getType() const { return m_type; }
void setAge( int age ) { m_age = age; }
int getAge() const { return m_age; }
void setWeight( float weight ) { m_weight = weight; }
float getWeight() const { return m_weight; }
virtual std::string speak() = 0; // Purely Virtual All Derived Class Must Implement This
// Abstract Class Can Not Be Instantiated
}; // Animal
class Dog : public Animal {
public:
Dog( int age, float weight ) : Animal( AnimalType::MAMMAL, age, weight ) {}
virtual ~Dog() {}
std::string speak() { return std::string( "rough" ); }
}; // Dog
With this structure you can create only the Dog object somewhere else in your source code.
Now to demonstrate a protected constructor using the same example above:
class Animal {
public:
enum AnimalType {
AMPHIBIAN,
BIRD,
FISH,
MAMMAL,
REPTILE,
}; // AnimalType
protected:
AnimalType m_type;
int m_age;
float m_weight;
std::string m_strVoice;
public:
virtual ~Animal() {} // Virtual Due To Inheritance
AnimalType getType() const { return m_type; }
void setAge( int age ) { m_age = age; }
int getAge() const { return m_age; }
void setWeight( float weight ) { m_weight = weight; }
float getWeight() const { return m_weight; }
virtual std::string speak() = 0; // Purely Virtual All Derived Class Must Implement This
// Abstract Class Can Not Instantiate
protected:
Animal( AnimalType type, int age, float weight ) :
m_type( type ), m_age( age ), m_weight( weight ) {}
// Constructor Is Protected - Doesn't Necessarily Make It Abstract
// But Prevents Outside Code From Accessing This Constructor Only
// Allowing Either Derived Classes Or Friends To Access This Constructor
}; // Animal
class Mammal : public Animal {
public:
virtual std:string speak() = 0;
protected:
Mammal( int age, float weight ) : Animal( AnimalType::MAMMAL, age, weight ) {}
}; // Mammal
class Dog : public Mammal {
public:
Dog( int age, float weight ) : Mammal( age, weight ) {}
virtual ~Dog() {}
std::string speak() { return std::string( "rough" ); }
}; // Dog
In the second case here, both Animal & Mammal can not be constructed as an object from somewhere else but Dog can. This is due to the protected constructor. Here both Animal & Mammal represent a concept & not an object, but Dog does represent an object. I hope this helps you.