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



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

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

这是我的问题:由于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;
}  

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

不相关,iCont1 == iCont2比较两个指针(也称为地址(是否相等,*iCont1 == *iCont2比较两个值(也称为对象(是否相等。 可以把第一个问题想象成问两栋房子的街道地址是否相同,第二个问题是两栋房子看起来一样。这两栋房子可能看起来一样,但它们仍然有不同的街道地址。但是,如果两个街道地址相同,您就知道只涉及一所房子。这两种比较彼此非常不同

请记住,它们是 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使用定义的重载==检查相等性。

最新更新