多态性C++

3

我希望我的代码能够打印出:

B B
A B
B A

但它会打印输出。
Item Item
Item Item
Item Item

代码:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

struct Item {
    Item(){}
    virtual void method1 (Item x, Item y) {cout << "Item Item\n";}
};

struct A : public Item {
    A(){}
};

struct B : public Item {
    B(){}
    virtual void method1 (B x, B y) {cout << "B B\n";}
    virtual void method1 (A x, B y) {cout << "A B\n";}
    virtual void method1 (B x, A y) {cout << "B A\n";}
};

int main ( void ) {
    Item * a[2];
    a[0] = new B; a[1] = new A;
    a[0]->method1(*a[0], *a[0]);
    a[0]->method1(*a[1], *a[0]);
    a[0]->method1(*a[0], *a[1]);
}
5个回答

5
您没有使用适当的参数覆盖 method1,因此它会一直调用Item类中的 method1
Item * a[2];

所以*a[0]*a[1]都是Item类型。这会导致你调用以下内容:
a[0]->method1(*a[0], *a[0]);
a[0]->method1(*a[1], *a[0]);
a[0]->method1(*a[0], *a[1]);

需要调用在基类 Item 中定义的 method1(Type,Type) 方法。
你应该在子类中使用 相同的参数 重写此方法,以便能够调用子类中的方法。

这是我认为你试图做的事情:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

struct Item {
    Item(){}
    virtual void method1 (Item x, Item y) {cout << "Item Item\n";}
    virtual void method2 (Item x, Item y) {cout << "Item Item\n";}
    virtual void method3 (Item x, Item y) {cout << "Item Item\n";}
};

struct A : public Item {
    A(){}
};

struct B : public Item {
    B(){}
    virtual void method1 (Item x, Item y) {cout << "B B\n";}
    virtual void method2 (Item x, Item y) {cout << "A B\n";}
    virtual void method3 (Item x, Item y) {cout << "B A\n";}

};

int main ( void ) 
{
    Item * a[2];
    a[0] = new B; a[1] = new A;
    a[0]->method1(*a[0], *a[0]);
    a[0]->method2(*a[1], *a[0]);
    a[0]->method3(*a[0], *a[1]);
}

这将为您提供所需的输出结果:
output:
B B
A B
B A

在Child类中适当地重写了method1()、method2()和method3(),因此当通过指向Child类对象的指针调用时,它们会被调用。


4
< p > a 的类型是指向 Item 指针的数组。编译器必须在编译时决定调用哪个方法,而不是运行时。由于它只知道参数的类型,即 Item,因此它调用的是该版本。


4
你在类 B 中对 method1 的重载没有覆盖到 Item 中的虚方法。因此,当你调用 someItem->method1 时,它不会使用这些重载。
看起来你想要所谓的“多分派”,但 C++ 并不直接支持。请参见 http://en.wikipedia.org/wiki/Multiple_dispatch#C.2B.2B 获取一些讨论和解决方法。

0

您已更改派生类中函数的签名。现在它是一个全新的虚函数。在派生时不应更改参数类型。只允许更改虚函数的返回类型,即使是基类的派生也应如此。基本上,在这种情况下,您并没有真正使用运行时多态性。


它们都支持多态性 - 在C++中,structclass在默认访问修饰符(public vs. private)方面有所不同。 - wkl

0
被调用的函数基于参数的静态类型而非动态类型。因此,它们都是“Item”。您正在寻找一种称为多方法的语言特性,这在C++中不存在,但可以通过一些工作来模拟。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接