当我尝试通过继承 class 的指针使用重新加载的友元函数时,它使用来自基础 class 的函数

When I am trying to use reloaded friend function by pointer from inherited class, it uses function from base class

我提前为我歪歪扭扭的英语表示歉意(如果有任何明显的错误,我很乐意知道) 我的问题是不能使用继承 class 的重载函数。 我创建了指向 Base class 的指针数组,并且在程序创建对象期间,它可以是 base class 或继承的。在使用重载函数 (operator<<) 时,它不断使用 base class 的选项,但是当我创建两个单独的对象时(Base class, Inherited class from base class), 重载运算符工作得很好。我应该往哪个方向挖? 有代码

#include <iostream>
#include "port.hpp"
using namespace std;
int main()
{
    port *p_port[2];
    p_port[0] = new VintagePort("BrandONe", 10, "NickName", 19978);
    p_port[1] = new port("BrandNameTwo","StyleTwo",1);
    for (int i = 0; i < 2; i++)
    {
        cout << *p_port[i] << endl;
    }
    for (int i = 0; i < 2; i++)
        delete p_port[i];
    
    cout << endl;
    port p("BrandNameTwo","Style",2);
    VintagePort vp("BrandName",19,"NickName",1982);
    cout << p << endl;
    cout << vp << endl;
}
#ifndef PORT_HPP_
#define PORT_HPP_
#include <iostream>
class port
{
private:
    char *brand;
    char style[20];
    int bottles;

public:
    port(const char *br = "none", const char *st = "none", int b = 0);
    port(const port &p);
    virtual ~port() { delete[] brand; }
    port &operator=(const port &p);
    port &operator+=(int b);
    port &operator-=(int b);
    int BottleCount() const { return bottles; }
    virtual void Show() const;
    friend std::ostream &operator<<(std::ostream &os, const port &p);
};
class VintagePort : public port
{
private:
    char *nickname;
    int year;

public:
    VintagePort();
    VintagePort(const char *br, int b, const char *nn, int y);
    VintagePort(const VintagePort &vp);
    ~VintagePort() { delete[] nickname; }
    VintagePort &operator=(const VintagePort &vp);
    void Show() const;
    friend std::ostream &operator<<(std::ostream &out, const VintagePort &vp);
};

#endif
#include "port.hpp"
using std::ostream;
port::port(const char *br, const char *st, int b)
{
    brand = new char[strlen(br) + 1];
    strcpy(brand, br);
    strcpy(style, st);
    bottles = b;
}
port::port(const port &p)
{
    brand = new char[strlen(p.brand) + 1];
    strcpy(brand, p.brand);
    strcpy(style, p.style);
    bottles = p.bottles;
}
port &port::operator=(const port &p)
{
    if (this == &p)
        return *this;
    delete[] brand;
    brand = new char[strlen(p.brand) + 1];
    strcpy(brand, p.brand);
    strcpy(style, p.style);
    bottles = p.bottles;
    return *this;
}
port &port::operator+=(int b)
{
    bottles += b;
    return *this;
}
port &port::operator-=(int b)
{
    bottles -= b;
    return *this;
}
void port::Show() const
{
    std::cout << "Brand: " << brand;
    std::cout << "\nKind: " << style;
    std::cout << "\nBottles: " << bottles << std::endl;
}
ostream &operator<<(ostream &out, const port &p)
{
    out << p.brand << ", " << p.style << ", "
        << p.bottles << std::endl;
    return out;
}
VintagePort::VintagePort()
{
    nickname = nullptr;
    year = 0;
}
VintagePort::VintagePort(const char *br, int b, const char *nn, int y)
    : port(br, "vintage", b)
{
    year = y;
    nickname = new char[strlen(nn) + 1];
    strcpy(nickname, nn);
}
VintagePort::VintagePort(const VintagePort &vp) : port(vp)
{
    nickname = new char[strlen(vp.nickname) + 1];
    strcpy(nickname, vp.nickname);
    year = vp.year;
}
VintagePort &VintagePort::operator=(const VintagePort &vp)
{
    if (this == &vp)
        return *this;
    port::operator=(vp);
    delete[] nickname;
    nickname = new char[strlen(vp.nickname) + 1];
    strcpy(nickname, vp.nickname);
    year = vp.year;
    return *this;
}
void VintagePort::Show() const
{
    std::cout << "\nNickname: " << nickname << std::endl;
    port::Show();
}
ostream &operator<<(ostream &out, const VintagePort &vp)
{
    out << vp.nickname << ", ";
    // operator<<(os, (const port &)vp);
    operator<<(out, (const port &)vp);
    return out;
}

这里是程序的结果

BrandONe, vintage, 10

BrandNameTwo, StyleTwo, 1


BrandNameTwo, Style, 2

NickName, BrandName, vintage, 19

我是新来的,抱歉,如果我做错了什么

重载和覆盖是完全不同的事情。

在编译时选择重载,使用静态类型。
由于数组元素的类型是 port*,因此选择了 port& 重载。

如果您想要一个“动态”operator<<,请创建一个接受基 class 并仅分派给您可以覆盖的虚拟成员函数的函数。

示例:

class port
{
    // ...
public:
    virtual std::ostream& print(std::ostream* os) const
    {
        out << brand << ", " << style << ", "
            << bottles << std::endl;
        return out;
    }
    
};


std::ostream& operator<<(std::ostream& os, const port& p)
{
    return p.print(os);
}

class VintagePort : public port
{
    // ...
public:
    std::ostream& print(std::ostream& out) const override
    {
        out << vp.nickname << ", ";
        return port::print(out);
    }
};