2013-03-24 7 views
8

Скажем, у нас есть это:Чистые виртуальные методы в производном абстрактном классе

class A 
{ 
    public: 
    virtual void foo() = 0; 
}; 

class B: public A 
{ 
    public: 
    virtual void foo() = 0; 
}; 

компилятор не бросает никакой ошибки, я думаю, его потому, что B также является абстрактным классом, и как таковой он не должен осуществлять foo от A Но что означает такая конструкция?

1) Есть foo с B hide foo от A?

2) Первый класс, который наследует от B и не является абстрактным классом, это должно обеспечить две реализации, как:

class C: public B 
{ 
    public: 
    virtual void A::foo() {}; 
    virtual void B::foo() {}; 
}; 

Компилятор жалуется, только если реализация B::foo() отсутствует, но не жалуется на отсутствие A::foo().

В целом: это способ скрыть чистые виртуальные методы?

+1

Как именно вы скрыть это? – Alon

+0

Если я не предоставляю реализацию для A :: foo() в C, я также могу создать экземпляр объекта C. Так что C всегда можно создать, даже если A :: foo() отсутствует. Поэтому я подумал, что каким-то образом A :: foo() не требуется в C, поэтому «скрыто». – Juergen

+1

Поскольку B наследует A .. – Alon

ответ

8

При первом провозглашают:

class A 
{ 
    public: 
    virtual void foo() = 0; 
}; 

вы объявляете метод foo общественности, виртуальный и чистый. Когда класс содержит хотя бы чистый метод, он называется аннотация. Что это значит? Это означает, что класс не может быть создан, потому что ему нужны реализации чистых методов.

Очевидно, что вы можете наследовать от абстрактного класса (я бы сказал, что вы вынуждены это делать, иначе зачем нужен абстрактный класс, который вы не используете, за исключением предоставления интерфейса для наследования?) и вы также можете наследовать от абстрактного класса и не реализовывать некоторые или все чистые методы родительского класса; В этом случае дочерний класс является абстрактным, а также, что в случае вашего класса B:

class B: public A 
{ 
    public: 
    virtual void foo() = 0; 
}; 

В B можно легко опустить virtual void foo() = 0; декларации, поскольку определение уже наследуется от базового класса. В этом случае класс B является абстрактным классом, и, следовательно, не может быть реализовано, так же, как А.

Чтобы ответить на ваши вопросы более непосредственно:

ли foo от B шкуры foo от А?

Нет, это не так. Оба они объявляют чистый метод (который на самом деле тот же метод), поэтому нет ничего действительно скрыть.

Первый класс, который наследуется от B и не является абстрактным классом, должен ли он предоставить две реализации, подобные предоставленной?

Нет, конечно нет. Как уже говорилось выше, они же метод, поэтому, если класс C должен обеспечить реализацию foo он должен просто реализовать foo:

class C: public B 
{ 
    public: 
    virtual void foo() {}; 
}; 
+0

Действительно ли 'Virtual' требуется в классе C. Не может быть просто' void foo() {}; '? –

+0

Согласно стандарту C++, это не требуется. Я считаю, что это более читаемо. – Shoe

7

0) Компилятор не проливает ошибку ...

Это будет сгенерировано сообщение об ошибке при попытке создать объект из A или B, которые они абстрактны. Не когда вы наследуете и объявляете их.

 

1) Есть ли Foo от B скрыть обув от А?

№ Обложка A::foo не скрывает ее.

 

2) Первый класс, который наследует от B и не является абстрактным классом, это должно обеспечить две реализации ...

Нет, просто переопределить foo и сделать для него одну реализацию.

 

class C : public B 
{ 
public: 
    virtual void foo() 
    { 
     std::cout << "ABCD" << std::endl; 
    } 
}; 


int main() 
{ 
    C c; 
    A *a = &c; 
    a->foo(); // Prints ABCD string and proofs B::foo doesn't hide A::foo 
} 
+0

Если B :: foo() не скрывает A :: foo(), то почему C разрешено НЕ реализовывать его? – Juergen

+1

Если вы хотите получить объект из 'C', тогда он должен реализовать' foo' – deepmax

+2

Нет, 'B :: foo' - это не то же самое, что' A :: foo', и он скрывает его (а также переопределяет) , –

1

Я составил свой код с GCC 4.5.3, он дал следующие сообщения об ошибках:

error: cannot define member function ‘A::foo’ within ‘C’ 
error: cannot define member function 'B::foo' within 'C' 

В вас, например, как класс A и B являются абстрактными классами начиная с обув является чисто виртуальным. Они определяют только то, что производный класс B должен реализовывать поведение foo, так как по умолчанию не используется поведение (если производный класс больше не абстрактный).

Question 1:Does foo from B hide foo from A?

С foo в B и A имеет точно такое же имя, так же подпись и Foo является виртуальной в базовом классе, поэтому он не скрывает, это переопределение.FYI: функция производного класса overrides функция базового класса, если сигнатура одинаков и объявлена ​​виртуальной в базовом классе. Если вы вызываете его через указатель или ссылку на базовый класс, вызывается функция в производном классе . Он «переопределяет» тот, что находится в базовом классе. Hiding только вступает в игру, если вы вызываете не виртуальную функцию с помощью указателя или ссылки или непосредственно с объекта производного класса . A Функция производного класса скрывает все базовые функции класса с тем же именем.

Question 2: The first class which inherits from B and is not an abstract class, does it have to provide two implementations

Нет, вы можете сделать следующее:

class C: public B 
    { 
    public: 
     virtual void foo() 
     { 
     cout << "foo defined in c" <<endl; 
     } 
}; 
+0

Я подтверждаю, что gcc действительно бросает сообщения об ошибках, а визуальный компилятор C++ этого не делает. – Juergen

+1

@Juergen Спасибо, что подтвердили это. – taocp

Смежные вопросы