Базовый класс без экземпляров? - PullRequest
1 голос
/ 25 января 2020

Я уверен, что я не первый, кто задает этот вопрос, но я не могу найти никакого ответа на него.

Мне нужен базовый класс, от которого наследуются несколько классов. Все унаследованные классы имеют некоторые функции (с реализацией) и общие переменные и имеют некоторые собственные переменные и функции (разные функции для каждого производного класса). Общие члены я хотел бы объединить в базовом классе. Дело в том, что базовый класс должен быть просто базовым, и я не хочу, чтобы из базового класса делались какие-либо экземпляры. Как мне это сделать?

Если приведенное выше описание неясно, возможно, это делает его более понятным: допустим, я хочу млекопитающих базового класса и производного класса, таких как человек, обезьяна, синий кит и т. Д. c. Я хочу создать экземпляры человека, обезьяны, синего кита и т. Д. c. но не млекопитающих.

Я где-то читал, что конструктор можно разместить как приватный, но мне нужен конструктор publi c производных классов

Ответы [ 3 ]

2 голосов
/ 25 января 2020

Создание абстрактного базового класса - это ваше решение.

Если вы не хотите делать какой-либо метод базового класса чисто виртуальным, вы можете сделать деструктор чисто виртуальным

#include <iostream>
using namespace std;

class IMammal //I for Interface
{
    public:
        virtual ~IMammal() = 0; //Makes the class abstract, Pure virtual destructor
};

IMammal::~IMammal() //Its necessary or ld will complain
{
    cout << "In ~IMammal" << endl;
}

class Ape : IMammal
{

};

int main()
{
//    IMammal m; // error: cannot declare variable ‘m’ to be of abstract type ‘IMammal’
    Ape a;
}
2 голосов
/ 25 января 2020

Поскольку каждый метод реализован в базовом классе, использование защищенного конструктора позволит вам добавить дополнительные переменные-члены в производный класс, не имея возможности создать базу. Чтобы сделать это еще более очевидным, я бы, вероятно, поместил базовый класс в другое пространство имен, чтобы вызывающий получил сильный намек на то, что ему не следует даже пытаться создать его.

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
2 голосов
/ 25 января 2020

Я думаю, что предложение Алана Биртлса действительно может сработать. Проверьте этот вопрос Каковы практические применения защищенного конструктора?

Все функции, которые у меня были бы в базовом классе, имеют реализацию в базовом классе. В противном случае использование виртуальной функции также может быть вариантом. Я проверил этот сайт https://www.geeksforgeeks.org/pure-virtual-functions-and-abstract-classes/ может быть, это полезно для других.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...