【问题标题】:Multiple inheritance order used in function resolution?函数解析中使用的多重继承顺序?
【发布时间】:2013-02-21 18:13:27
【问题描述】:

有一个关于继承和混合接口类的问题贴出:
Multiple inheritance of interfaces in C++
这让我想到了这个问题:继承顺序会影响函数解析规则吗?

给定:

struct Binary_Stream_Read_Intf
{
  virtual void load_from_buffer(uint8_t*& buffer_ptr) = 0;
};

struct Binary_Stream_Write_Intf
{
  virtual void store_to_buffer(uint8_t*& buffer_ptr) const = 0;
};

struct Binary_Stream_Read_Write_Intf
: public Binary_Stream_Read_Intf,
  public Binary_Stream_Write_Intf
{ ; };

struct Binary_Stream_Write_Read_Intf
: public Binary_Stream_Write_Intf,
  public Binary_Stream_Read_Intf
{ ; };

这是我的问题:

  1. Binary_Stream_Read_Write_IntfBinary_Stream_Write_Read_Intf 一样吗?
  2. 在函数调用中可以用一个代替另一个吗?
  3. 它们都可以用于需要 Binary_Stream_Read_Intf?

【问题讨论】:

  • 你先问一个一般性的问题,然后再问 3 个特定于你的例子的问题。人们应该回答所有 4 个问题,还是只回答最后 3 个问题?
  • 一般来说,如果继承的类包含相同的属性或方法(在您的示例中不是这种情况),则排序可能是一个问题。但是,当进行模棱两可的调用时,编译器会出错,因此即使在这种情况下也没关系。

标签: c++ interface multiple-inheritance name-lookup


【解决方案1】:

1 不,它们不一样。您用两个不同的名称声明了两个不同的结构。编译器会将它们视为完全不同的。这类似于说

class Newspaper
{
    int volume;
};
class TelevisionAudioControl
{
    int volume;
};

这两个是一样的吗?它们具有相同成员的事实不足以让编译器将它们视为相同。但是,在我的示例中,由于它们确实共享相同的成员,因此您可以通过将一个地址显式转换为另一个来避免:

TelevisionAudioControl tac;
Newspaper * n = (Newspaper *)&tac;

n->volume 仍然可以工作。然而,这更多是由于指针的魔力和危险性而不是其他任何东西,并且依赖于编译器的行为方式,技术上未定义的行为也是如此。如果它确实有效,那么它只有在所有成员都相同且顺序相同时才有效。我不确定在你的例子中,函数的顺序是一样的,所以我不能保证你能做那种糟糕的施法魔法。由于这些函数是虚拟的,因此您可能会通过虚拟函数指针表,并且没问题。

2 如果函数正在调用 Binary_Stream_Read_Write_Intf 或 Binary_Stream_Write_Read_Intf,则否。编译器只接受该类或从它继承的任何东西,并且两个类都不是另一个类的后代。 (不过,您可以说它们是兄弟姐妹。)但是,如果该函数调用 Binary_Stream_Write_Intf 或 Binary_Stream_Read_Intf,那么您可以,因为这是调用它们共同的父级。像往常一样,如果没有共同继承,那么你不能替代。如果函数需要一个通用的超类,是的,任何一个都可以。

3 它们都继承自 Binary_Stream_Read_Intf,所以是的。

【讨论】:

  • 实际上,您的演员表是未定义的行为。
  • @MatthieuM。这对我来说似乎很安全,但我相信你的话并更新了我的回复。
  • 请注意,这两个类都可以使用它们的公共字段在模板中工作,因此虽然它们在 C++ 术语中属于不同的“类型”,但它们确实共享一个共同的“签名”(什么是正确的 C++ 术语?)。
  • @didierc:实际上,强制转换对于 C++ 中的类型子集是安全的。在 C++03 中,这个子集是 POD 类型的子集,在 C++11 中,这个子集是 trivial-layout 类型的子集(定义更宽松)。对于具有简单布局的两种不同类型,并共享一个共同的属性起始序列(相同类型以相同顺序布局),然后通过一种或另一种类型访问这些属性是安全的。不幸的是,这些类型不是普通布局(我认为),因为属性是private
  • 嗯,正确,那里的属性不公开。感谢您指出了这一点。我最初的评论仅对公共属性的公共子集有效。
【解决方案2】:
  1. 不,就像struct Foo {};struct Bar {};不一样。

  2. 不,见上文。

  3. 是的。

【讨论】:

    猜你喜欢
    • 2016-11-21
    • 2015-02-11
    • 2016-08-09
    • 2011-11-24
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    相关资源
    最近更新 更多