为什么我能够取消引用指向抽象类的指针?

时间:2017-08-08 20:40:48

标签: c++ pointers abstract-class

在下面的代码中,IContainer是一个纯抽象类:它不包含任何非纯虚方法。在这种情况下,我不希望能够实例化IContainer类型的对象,但是我希望能够在IContainer*中保存派生类的实例。

在下面的main中,我创建了一些实现SimpleContainer的具体类IContainer的实例。接下来,我在一些SimpleContainer变量中存储了指向这些IContainer*的指针。

这是我的问题:由于IContainer是一个抽象类,我无法实例化它。但是,在main的底部,您可以看到我取消引用我的IContainer指针以检查相等性。为什么我能这样做?另外,iCont1 == iCont2*iCont1 == *iCont2之间是否存在差异?

#include <iostream>

class IContainer{
    public:
        virtual bool operator==(const IContainer& aICont) const = 0;
        virtual int getVal() const = 0;
};

class SimpleContainer : public IContainer{
    public:
        SimpleContainer(int val) : val(val){};
        int getVal() const override {return val;}
        bool operator==(const IContainer& aICont) const override
        {
            return val == aICont.getVal();
        }
    private:
        int val;
};

int main(){
    SimpleContainer cont1(1), cont2(2), cont3(1);
    IContainer* iCont1 = &cont1;
    IContainer* iCont2 = &cont2;
    IContainer* iCont3 = &cont3;

    std::cout << "iCont1 == iCont2 -> " << (iCont1 == iCont2 ? "true" : "false") << " || Expecting -> " << "false" << std::endl;        
    std::cout << "*iCont1 == *iCont2 -> " << (*iCont1 == *iCont2 ? "true" : "false") << " || Expecting -> " << "false" << std::endl; 
    std::cout << "iCont1 == iCont3 -> " << (iCont1 == iCont3 ? "true" : "false") << " || Expecting -> " << "false" << std::endl; 
    std::cout << "*iCont1 == *iCont3 -> " << (*iCont1 == *iCont3 ? "true" : "false") << " || Expecting -> " << "false" << std::endl; 
    return 0;
}  

2 个答案:

答案 0 :(得分:4)

请记住,它们是IContainer指针,但那里没有存储IContainer。您正在取消引用子类,而不是父抽象类。

SimpleContainer cont1(1), cont2(2), cont3(1);
IContainer* iCont1 = &cont1;
IContainer* iCont2 = &cont2;
IContainer* iCont3 = &cont3;

上面你创建了一些SimpleContainers,你说嘿,我想引用这些作为IContainers,因为我可以有相同的父类的其他类似的对象,我可以将它们组合在一起,因为我的抽象类将处理如何使用这些功能。此过程并未改变SimpleContainer仍存储在同一位置的事实。你所有的指针都在说那个位置有某种容器。

iCont1 == iCont2检查两个对象的内存位置是否相同

*iCont1 == *iCont2使用您定义的==重载检查相等性。

答案 1 :(得分:2)

你是对的,你不能拥有抽象类IContainer的实例,但取消引用指针并没有给你一个实例,它会给你一个引用IContainer&),完全允许。它是对(未指定的)派生类型的引用。由于它是一个引用,您可以使用点语法或其他运算符来访问接口的方法,它将使用普通的虚拟查找来查找正确的重写方法来调用,就像它是一个指针一样。所以,是的,你正在做的事情是有效的,而且是安全的。

不相关,iCont1 == iCont2比较两个指针(也称为地址)是否相等,*iCont1 == *iCont2比较两个值(即对象)是否相等。想想第一个问两个房子是否有相同的街道地址,第二个是两个房子看起来是一样的。两个房子可能看起来一样,但他们仍然有不同的街道地址。但如果两个街道地址相同,你知道只有一个房子涉及。两个比较非常彼此不同。