Поскольку каждый метод реализован в базовом классе, использование защищенного конструктора позволит вам добавить дополнительные переменные-члены в производный класс, не имея возможности создать базу. Чтобы сделать это еще более очевидным, я бы, вероятно, поместил базовый класс в другое пространство имен, чтобы вызывающий получил сильный намек на то, что ему не следует даже пытаться создать его.
namespace detail
{
class Mammal
{
public:
void layEggs() { /*implementation*/ }
protected:
//Stop anyone creating a Mammal
//Can still be accessed by derived classes,
//and anyone that Mammal has declared a friend
Mammal(int age) : age_(age);
int age_;
};
}
class Dog : public detail::Mammal
{
public:
//Dog is still allowed to access Mammal constructor
Dog(int age, const std::string& name) :
Mammal(age), name_(name)
{}
protected:
std::string name_;
};
Редактировать: я первоначально ответил, не понимая, что каждый метод был реализован в базовом классе
. Вы можете сделать это, сделав класс абстрактный класс . Вы делаете это, создавая хотя бы одну функцию чисто виртуальную функцию .
class Mammal
{
public:
void layEggs()
{
//implemented in base
}
virtual std:string speak() = 0 //pure virtual, so class cannot be instantiated
};
class Dog : public Mammal
{
public:
virtual std::string speak()
{
return "woof";
}
};
Поскольку Mammal содержит функцию pure virtual
, из нее невозможно создать переменную. Однако Dog реализовал все функции, поэтому можно создать переменную.
Mammal m; //will result in compiler error, because what would m.speak() do?
Dog d; //is allowed, because we know what d.speak() should do