多继承指针比较 [英] Multiple inheritance pointer comparison

查看:156
本文介绍了多继承指针比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类 Derived 直接从两个基类继承, Base1 Base2 。我想知道如果它是安全的,一般来说,比较指针与基类,以确定它们是否是相同的 Derived object:

  Base1 * p1; 
Base2 * p2;

/ *
*这里发生的东西。 p1和p2现在指向它们的
*基本类型或Derived的有效对象
* /

//断言(p1 == p2); //这是非法的
assert(p1 == static_cast< Base1 *>(p2)); //这个可以吗?
assert(static_cast< Derived *>(p1)== static_cast< Derived *>(p2)); //这个怎么样?

指针保证有效,但不一定指向派生对象。我的猜测是,这可能是好的,但我想知道是否从技术C ++的角度来确定。我实际上从来没有对指针进行任何操作,我只想知道他们是否指向同一个对象。



编辑:似乎是安全的,如果我能保证 p1 p2 指向 Derrived 对象。我基本上想知道如果它是安全的,如果他们不 - 如果一个或两个指向一个基础对象,比较必然失败?再次,我可以保证指针是有效的(即 p1 不会指向一个 Base2 对象,反之亦然)

解决方案

好吧,不行,不行。



我个人是一个学习示例的大粉丝,所以这里是一个:

  #include< iostream& 

class Base1
{
public:
Base1()
{
numberBase1 = 1;
}

int numberBase1;
};

class Base2
{
public:
Base2()
{
numberBase2 = 2;
}

int numberBase2;
};

类派生:public Base1,public Base2
{
public:
Derived()
{
numberDerived = 3;
}

int numberDerived;
};

int main()
{
Derived d;
Base1 * b1 =& d;
Base2 * b2 =& d;

std :: cout<< d:<< & d< ,b1:< b1 << ,b2:< b2 << ,d.numberDerived:<< &(d.numberDerived)<< std :: endl;

return 0;
}

在我的电脑上输出一个run-through:
d:0035F9FC ,b1:0035F9FC,b2:0035FA00,d.numberDerived:0035FA04



如果我们将d的地址定义为0,则b1为0,b2为+ 4,d的个数为+8。这是因为我的机器上的int是4个字节长。



基本上,你必须看看C ++在内部表示类的布局:

 地址:类别:
0 Base1
4 Base2
8派生

..所以总的来说,实例化Derived类将为派生类的基类分配空间,最后为派生对象本身。因为我们在这里有3个整数,这将是12个字节。



现在,你要问(除非我误解了)是如果你可以比较地址不同的基类指针相互指向,看看它们是否指向同一个对象,答案是否 - 不直接至少,如在我的例子中,b1将指向0035F9FC,而b2将指向0035FA00。在C ++中,这种抵消是在编译时完成的。



你可以用RIIA和sizeof()做一些魔法,并确定偏移b2应该有多少相当于b1,但是你会遇到各种其他麻烦像虚拟。总之,我不会推荐这种方法。



一个更好的方法是转换为Derived *像ialiashkevich说,但是,如果你的对象不是Derived *的实例。



(免责声明;我在3-4年没有使用C ++,所以我可能对我的游戏有点不高兴:))


I have a class Derived that inherits directly from two base classes, Base1 and Base2. I'd like to know if it's safe, in general, to compare pointers to the base classes to determine if they are the same Derived object:

Base1* p1;
Base2* p2;

/*
 * Stuff happens here. p1 and p2 now point to valid objects of either their
 * base type or Derived
 */

//assert(p1 == p2); //This is illegal
assert(p1 == static_cast<Base1*>(p2)); //Is this ok?
assert(static_cast<Derived*>(p1) == static_cast<Derived*>(p2)); //How about this?

The pointers are guaranteed to be valid, but not necessarily to point to a Derived object. My guess is that this is probably fine, but I wanted to know if it was ok from a technical C++ perspective. I actually never do any operations on the pointers, I just want to know if they point to the same object.

EDIT: It seems to be safe if I can guarantee that p1 and p2 point to Derrived objects. I basically want to know if it is safe if they don't- if one or both point to a base object, will the comparison necessarily fail? Again, I can guarantee the pointers are valid (i.e., p1 would never point at a Base2 object or vice versa)

解决方案

Well, no, it won't work.

I'm personally a big fan of learning-by-example, so here's one:

#include <iostream>

class Base1
{
public:
    Base1()
    {
        numberBase1 = 1;
    }

    int numberBase1;
};

class Base2
{
public:
    Base2()
    {
        numberBase2 = 2;
    }

    int numberBase2;
};

class Derived : public Base1, public Base2
{
public:
    Derived()
    {
        numberDerived = 3;
    }

    int numberDerived;
};

int main()
{
    Derived d;
    Base1 *b1 = &d;
    Base2 *b2 = &d;

    std::cout << "d: " << &d << ", b1: " << b1 << ", b2: " << b2 << ", d.numberDerived: " << &(d.numberDerived) << std::endl;

    return 0;
}

One run-through on my computer outputted this: d: 0035F9FC, b1: 0035F9FC, b2: 0035FA00, d.numberDerived: 0035FA04

Soo.. If we define the address of d as 0, then b1 is 0, b2 is +4 and the number of d is +8. This is because an int on my machine is 4 byte long.

Basically, you have to look at the layout of how C++ internally represents a class:

Address:    Class:
0           Base1
4           Base2
8           Derived

.. So in total, instantiating a Derived class will allocate space for the base classes of the derived class, and finally make room for the derived object itself. Since we have 3 integers here, that'll be 12 bytes.

Now, what you're asking (unless I misunderstood something) is if you can compare the address of the different base class pointers to each other to see if they point to the same object, and the answer is no - Not directly at least, as in my example, b1 would point to 0035F9FC, while b2 would point to 0035FA00. In C++, this offsetting is all done at compile time.

You could probably do some magic with RIIA and sizeof() and determine how much of an offset b2 should have to be comparable to b1, but then you run into all kinds of other trouble like virtuals. In short, I would not recommend this approach.

A much better way would be to cast to Derived* like ialiashkevich said, however, that would impose a problem if your object was not an instance of Derived*.

(Disclaimer; I haven't used C++ in 3-4 years, so I might be a bit off my game. Be gentle :) )

这篇关于多继承指针比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆