2013-12-24 4 views
2

Рассмотрим следующий примерКак реализовать чистую виртуальную функцию

#include <iostream> 

struct PureVirtual { 
    virtual void Function() = 0; 
}; 

struct FunctionImpl { 
    virtual void Function() { 
     std::cout << "FunctionImpl::Function()" << std::endl; 
    } 
}; 

struct NonPureVirtual : public FunctionImpl, public PureVirtual { 
    using FunctionImpl::Function; 
}; 

int main() { 
    NonPureVirtual c; 
    c.Function(); 
} 

Compiler (GCC 4.9, Clang 3.5) завершается с ошибкой

test.cpp:18:20: error: variable type 'NonPureVirtual' is an abstract class 
    NonPureVirtual c; 
       ^
test.cpp:4:18: note: unimplemented pure virtual method 'Function' in 'NonPureVirtual' 
    virtual void Function() = 0; 
      ^

Но когда я не получить форму Pure Virtual все в порядке , Это странно, потому что стандарт 10.4.4 говорит

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

Они ничего не говорят о том, что такое конечный перехватчик, но я полагаю, что это должно быть FunctionImpl::Function(), особенно когда я сделал его доступным с помощью директивы. Так почему же Не чистый виртуальный абстрактный класс и как я могу это исправить?

+0

Казалось бы, вы путаете C++ с Java. Просто потому, что функции FunctionImpl и PureVirtual имеют методы одной и той же подписи, не делают реализацию другой. –

+0

Я предполагаю, что это выдержка из более крупной программы, и может быть, что фактическая проблема заключается в следующем: если вы не хотите, чтобы PureVirtual дважды был базовым классом, вы должны наследовать его практически ('public virtual PublicVirtual'). (Google для «виртуального наследования».) – Tobias

ответ

1

FunctionImpl::Function и PureVirtual::Function - это разные функции из разных классов.

Их соответствующие типы: void (FunctionImpl::*)() и void (PureVirtual::*)(). Поскольку PureVirtual и FunctionImpl являются несвязанными классами, эти типы функций не связаны.

Они имеют одно и то же имя и одинаковые параметры и тип возвращаемого значения, но поскольку они отличаются друг от друга, использование строки FunctionImpl :: Function не делает эту функцию переопределенной функцией в PureVirtual.

И если вы объявили переменную типа void (PureVirtual::*)(), вы бы не смогли назначить ей функцию FunctionImpl :: Function.

Другими словами, окончательное переопределение PureVirtual :: Function является оригинальным в PureVirtual, который является чисто виртуальным.

0

Когда вы получаете чистый виртуальный класс, вам нужно переопределить все чистые виртуальные функции, если вы хотите создать экземпляр класса. FunctionImpl не имеет никакого отношения к PureVirtual

Так

struct NonPureVirtual : public FunctionImpl, public PureVirtual { 
    using FunctionImpl::Function; 
}; 

не хватает, вам нужно реализовать пустоты функции в классе NonPureVirtual

struct NonPureVirtual : public FunctionImpl, public PureVirtual { 
    void Function() {} 
}; 
1

Следующий исходный код демонстрирует свой комментарий о виртуальном наследовании с примером. Он компилируется и работает нормально.

#include <iostream> 

struct PureVirtual { 
    virtual void Function() = 0; 
}; 

struct FunctionImpl : public virtual PureVirtual { 
    virtual void Function() { 
     std::cout << "FunctionImpl::Function()" << std::endl; 
    } 
}; 

struct NonPureVirtual : public FunctionImpl, public virtual PureVirtual { 
    using FunctionImpl::Function; 
}; 

int main() { 
    NonPureVirtual c; 
    c.Function(); 
} 


/* 
Local Variables: 
compile-command: "g++ ./test.cc" 
End: 
*/ 
Смежные вопросы