2012-01-24 55 views
3

基于我的研究,我认为这有一个很好的感觉,但希望得到确认。我一直在学习继承和虚拟方法的工作方式。继承和虚拟方法

在底部的代码中,运行main时会得到结果(上面的代码)。如果我将printType方法切换为非虚拟方式,则会打印出“AbstractClass”。

据我所知,使用“虚拟”表示该方法可能被覆盖 - 并总是选择该方法的“最后重新实现”,在这种情况下在ImplementationClass中。我的问题是:

1)这是否总是会发生?或者是否存在这样的情况:即使它是一种虚拟方法,您可能最终会使用AbstractClass(或其他类,如果它被多次继承)的方法被调用?

2)似乎你不能实例化一个包含虚拟方法的类的非指针。这是真的?

3)我假设在我的两个例子中没有什么不同,但我只有约80%的可信度。

非常感谢您的帮助,这整个虚拟方法的东西很难从阅读中找出来(这就是为什么我首先创建了一个虚拟项目!)。

after redefinition 
ImplementationClass 
printing from virtual method in ImplementationClass 

second set of examples 
ImplementationClass 
printing from virtual method in ImplementationClass 

#include <iostream> 
using namespace std; 

class AbstractClass{ 

public: 
    virtual void printStuff() = 0; 
    AbstractClass() {}; 
    ~AbstractClass() {}; 

    virtual void printType() { std::cout << "AbstractClass" << std::endl; } 
    // void printType() { std::cout << "AbstractClass" << std::endl; } 

}; 
class ImplementationClass : public AbstractClass { 

public: 
    void printStuff() { std::cout << "printing from virtual method in ImplementationClass" << std::endl;} 
    void printType() { std::cout << "ImplementationClass" << std::endl; } 
    void printStuffOnlyInDerived() {std::cout << "printing from NONvirtual method in ImplementationClass" << std::endl;} 


    ImplementationClass() {}; 
    ~ImplementationClass() {}; 
}; 




int main() { 

    AbstractClass * absClass; 
    ImplementationClass * impClass= new ImplementationClass; 

    absClass = impClass; 

    printf("\nafter redefinition \n"); 
    absClass->printType(); 
    absClass->printStuff(); 


    AbstractClass * absClassNonPtrImpClass = new ImplementationClass; 

    printf("\n second set of examples \n"); 
    absClassNonPtrImpClass->printType(); 
    absClassNonPtrImpClass->printStuff(); 


    return 0; 
} 
+0

不,它并不总是会发生。当在基类的构造函数中调用虚函数并且该函数尚未被覆盖时,原函数将被调用。 –

回答

1

1)这是否总是会发生?

有没有在那里你可以从抽象类的方法最终实例(或其它类,如果它继承了多次)被调用,即使它是一个虚拟的方法?

是的,如果没有在派生类中定义的,并不= 0 如果定义在派生类,您仍然可以调用基类的版本的BaseClass ::方法() ;

2)似乎你不能实例化一个包含虚拟方法的类的非指针。这是真的?

你可以实例化一个包含虚拟方法的类,但是如果它们= 0,那么它是抽象的,你不能。

+0

哦,很酷,我什至不知道absClass-> AbstractClass :: printType();将工作 – enderland

+0

是的,::是“范围解析运算符”。 – Foggzie

+0

@Gunther Fox:不,它并不总是会发生。当在基类的构造函数中调用虚函数并且该函数尚未被覆盖时,原函数将被调用。 –

1

1)是的,多态性始终有效。

2)你弄错了,你可以在自动存储中实例化类的对象。

你不能在你的例子中的原因是因为你的基类是抽象的。

此:

AbstractClass * absClass; 

仅声明一个指针的基类。它不会创建实际的对象。

以下是合法的:

ImplementationClass x; 

虽然ImplementationClass是一个多态型,您可以创建在自动存储对象(而不是你通过指针叫什么)。你可以这样做,因为基类中的抽象方法是在派生类中实现的。

+0

“2)你弄错了,你可以在自动存储中实例化类的对象。” 啊,好的,你的第二个例子回答了我要说的话。但是,你永远无法做AbstractClass * myAbsClass(如果AbstractClass包含一个虚拟方法?或者仅仅是我的情况,因为我有一个纯粹的虚拟方法吗?) – enderland

+0

@enderland是...所以? - “2)看来你不能实例化一个包含虚拟方法的类的非指针,这是真的吗?”这是不正确的,你可以实例化包含虚拟方法的类的非指针(???)。 –

+0

@enderland'AbstractClass * myAbsClass'不会实例化一个类,它只是一个指针声明。你可以有一个指向抽象类的指针声明。你不能做的是创建一个实例:'AbstractClass * myAbsClass = new AbstractClass''将失败,''AbstractClass myAbsClass;'将会失败。 –

3
  1. 是的,你可以明确地指定基类的方法,并调用它,即使是通过指针指向一个派生类(pDerived->Base::virtualMethod() - 这将调用Base的实施virtualMethod())。你也可以使用slice派生类对象,并且也会丢失多态性。

  2. 您不能用抽象方法(用= 0声明)创建类的对象,但您可以使用具有实现的虚拟方法创建类的对象。

+0

真棒,谢谢:)我可能错误地使用了“抽象”一词。 – enderland

+0

+1我想说的。还值得一提:你可以创建指针和引用形式的抽象类。 –

+1

* to * abstract classes ... –