Абстрактный класс в с ++ - PullRequest
1 голос
/ 15 ноября 2009

Допустим, у меня есть класс:

class Bad_Date
{
private:
const char* _my_msg;
public:
const char* msg() const
{
return _my_msg;
}
};

И я хотел бы, чтобы не было возможности создать какой-либо объект этого класса, но я действительно не хочу помещать что-либо еще туда и делать его чисто виртуальным fnc. Есть ли другой способ сделать этот класс абстрактным или мне нужно создать фиктивный fnc и объявить его чисто виртуальным? Спасибо.

Ответы [ 9 ]

10 голосов
/ 15 ноября 2009

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

Если вам не нужен виртуальный деструктор (т. Е. Класс не используется полиморфно), вы можете сделать конструктор защищенным (не приватным).

7 голосов
/ 15 ноября 2009

Сделать конструктор защищенным:

class Bad_Date
{
private:
const char* _my_msg;

// Add the 2 lines below:
protected:
    Bad_Date() {}

public:
const char* msg() const
{
return _my_msg;
}
};
7 голосов
/ 15 ноября 2009

Добавить чистый виртуальный деструктор.

3 голосов
/ 15 ноября 2009

Вы можете сделать деструктор чисто виртуальным, и это станет вашей "фиктивной функцией". т.е.

 class Bad_Date
 {
   private:
   const char* _my_msg;
   public:
   const char* msg() const { return _my_msg; }
   virtual ~Bad_Date() = 0;
 };

В любом случае, сделать виртуальный деструктор хорошей идеей для любого класса, который вы собираетесь использовать полиморфно, чтобы обеспечить надлежащую очистку экземпляров подкласса. Если вам нужно, чтобы Bad_Date выполнял какую-то работу в деструкторе, вы, конечно, не можете сделать деструктор чисто виртуальным. Создание защищенного конструктора (ов) Bad_Date - еще один жизнеспособный метод. Это гарантирует, что Bad_Date может быть создан только подклассом Bad_Date. К сожалению, это не помешает кому-то создать подкласс Bad_Date, просто чтобы действовать как фабрика для Bad_Date с.

Кроме того, существуют специальные расширения компилятора для создания абстрактных базовых классов, например, MSVC имеет __interface, а gcc имеет , раньше имел signature.

1 голос
/ 15 ноября 2009

Вы можете сделать конструктор приватным защищенным, переопределив конструктор по умолчанию:

class Bad_Date
{
    protected:
    Bad_Date() { }
    // rest of the class definition
};
0 голосов
/ 04 декабря 2009

Вам следует прочитать это , чтобы избежать распространенных ошибок с чисто виртуальными деструкторами.

0 голосов
/ 16 ноября 2009

Вы также можете сделать msg(), чисто виртуальный и одновременно обеспечить его реализацию.

class Bad_Date
{
private:
const char* _my_msg;
public:
virtual const char* msg() const = 0;
};

const char* Bad_Date::msg() const {
    return _my_msg;
}
0 голосов
/ 15 ноября 2009

Сделайте деструктор чисто виртуальным (абстрактным) - но не забудьте также дать ему реализацию, иначе вы никогда не сможете уничтожить объекты, полученные из Bad_Date:

class Bad_Date
{
    // ...

public:  // or maybe protected

    virtual ~Bad_Date() = 0;
};


Bad_Date::~Bad_Date()
{
}

Многие люди смущены сочетанием чисто виртуальных функций, которые также определены, думая, что это не имеет смысла. Но это не только законно, это требуется в некоторых случаях (например, чисто виртуальный dtor).

0 голосов
/ 15 ноября 2009

Мой C ++ ржавый, но все же:

Может быть, вы можете дать классу только приватный конструктор?

IIRC, абстрактные классы являются абстрактными именно потому, что они имеют хотя бы одну чисто виртуальную функцию ...

...