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

wes*_*yer 3 c++ abstract-class pointers

在下面的代码中,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;
}  
Run Code Online (Sandbox Code Playgroud)

Moo*_*uck 6

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

不相关,iCont1 == iCont2比较两个指针(又名地址)是否相等,并*iCont1 == *iCont2比较两个值(又名对象)是否相等。将第一个问题视为询问两栋房屋是否具有相同的街道地址,第二个问题询问两栋房屋是否具有相同的街道地址。这两栋房子可能看起来相同,但它们的街道地址仍然不同。但如果两条街道地址相同,您就知道只涉及一栋房子。两者的比较有很大不同。


Eas*_*ier 5

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

SimpleContainer cont1(1), cont2(2), cont3(1);
IContainer* iCont1 = &cont1;
IContainer* iCont2 = &cont2;
IContainer* iCont3 = &cont3;
Run Code Online (Sandbox Code Playgroud)

上面你创建了一些SimpleContainers,你说嘿,我想将它们引用为 IContainers,因为我可以拥有具有相同父类的其他类似对象,并且我可以像这样将它们分组在一起,因为我的抽象类将处理如何使用这些函数。SimpleContainer此过程并没有改变 a仍然存储在同一位置的事实。您的指针所做的只是表明该位置有某种容器。

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

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