답변:
순수 virtual
함수는 직접 인스턴스화 할 파생 유형으로 구현해야하지만 기본 유형은 여전히 구현을 정의 할 수 있습니다. (호출하여 완벽한 범위의 이름을 사용하여 (액세스 권한을 허용하는 경우) 파생 클래스는 명시 적으로 기본 클래스 구현을 호출 할 수 있습니다 A::f()
- 경우의 예에서 A::f()
있었다 public
또는 protected
). 다음과 같은 것 :
class B : public A {
virtual void f() {
// class B doesn't have anything special to do for f()
// so we'll call A's
// note that A's declaration of f() would have to be public
// or protected to avoid a compile time problem
A::f();
}
};
내가 생각할 수있는 유스 케이스는 다소 합리적인 기본 동작이있을 때이지만 클래스 디자이너는 기본 정렬 동작이 명시 적으로 만 호출되기를 원합니다. 파생 클래스가 항상 자체 작업을 수행하지만 공통된 기능 집합을 호출 할 수도 있습니다.
언어에 의해 허용되지만, 내가 일반적으로 사용하는 것으로 보이는 것은 아닙니다 (그리고 그것을 할 수 있다는 사실은 대부분의 C ++ 프로그래머, 심지어 경험이 많은 프로그래머를 놀라게하는 것처럼 보입니다).
분명히, 당신은 무엇을 오해하고 있습니다 = 0; 가상 기능 후 의미합니다.
= 0은 파생 클래스가 구현을 제공해야한다는 것을 의미하며 기본 클래스가 구현을 제공 할 수는 없습니다.
실제로 가상 함수를 순수 (= 0)로 표시하면 누군가가 Base :: Function (...)을 통해 명시 적으로 수행하지 않는 한 또는 호출되지 않기 때문에 정의를 제공 할 때 아무런 의미가 없습니다. 기본 클래스 생성자는 해당 가상 함수를 호출합니다.
이 방법의 장점은 파생 형식이 여전히 메서드를 재정의하지만 기본 또는 추가 구현을 제공한다는 것입니다.
파생 클래스에서 실행해야하는 코드가 있지만 직접 실행하지 않으려는 경우 강제로 재정의하려는 경우
코드는 정확하지만 모든 것이 자주 사용되는 기능은 아니지만 일반적으로 순수한 가상 소멸자를 정의하려고 할 때만 나타납니다.이 경우 구현을 제공 해야 합니다. 재미있는 점은 일단 그 클래스에서 파생되면 소멸자를 재정의 할 필요가 없다는 것입니다.
따라서 순수한 가상 함수의 현명한 사용법은 순수한 가상 소멸자를 "최종"키워드로 지정하는 것입니다.
다음 코드는 놀랍도록 정확합니다.
class Base {
public:
virtual ~Base() = 0;
};
Base::~Base() {}
class Derived : public Base {};
int main() {
// Base b; -- compile error
Derived d;
}
예를 들어 순수한 가상 소멸자에게 몸을 주어야합니다 :)
읽기 : http://cplusplus.co.il/2009/08/22/pure-virtual-destructor/
'가상 무효 foo () = 0;' 구문은 현재 클래스에서 foo ()를 구현할 수 없다는 것을 의미하지는 않습니다. 또한 파생 클래스에서 구현해야한다는 의미는 아닙니다 . 당신이 나를 때리기 전에, 다이아몬드 문제를 관찰 해 봅시다 :
class A
{
public:
virtual void foo()=0;
virtual void bar();
}
class B : public virtual A
{
public:
void foo() { bar(); }
}
class C : public virtual A
{
public:
void bar();
}
class D : public B, public C
{}
int main(int argc, const char* argv[])
{
A* obj = new D();
**obj->foo();**
return 0;
}
이제 obj-> foo () 호출로 B :: foo () 및 C :: bar ()가 발생합니다.
알다시피 ... 순수 가상 메소드는 파생 클래스에서 구현할 필요가 없습니다 (foo ()는 C 클래스에서 구현되지 않습니다-컴파일러는 컴파일됩니다) C ++에는 많은 허점이 있습니다.
내가 도울 수 있기를 바랍니다 :-)
C
예제에서 유형의 객체를 인스턴스화 할 수 없습니다 . 에서 D
구현을 가져 foo
오기 때문에 유형의 객체를 인스턴스화 할 수 있습니다 B
.
구현 본문과 함께 순수한 가상 메소드 를 사용하는 한 가지 중요한 유스 케이스 는 추상 클래스를 원하지만 클래스에 순수 가상으로 만들 적절한 메소드가없는 것입니다. 이 경우 클래스의 소멸자를 순수 가상으로 만들고 원하는 구현 (빈 바디)을 넣을 수 있습니다. 예로서:
class Foo
{
virtual ~Foo() = 0;
void bar1() {}
void bar2(int x) {}
// other methods
};
Foo::~Foo()
{
}
이 기술은 Foo
클래스를 추상화하여 결과적으로 클래스를 직접 인스턴스화 할 수 없습니다. 동시에 Foo
클래스 추상화 를위한 추가 순수 가상 메소드를 추가하지 않았습니다 .
deported
. (.inl 또는 .cpp에서 일반적인 파일 이름 지정 방법을 나타냅니다).