首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >虚方法,operator=(),operator<<();

虚方法,operator=(),operator<<();
EN

Stack Overflow用户
提问于 2015-06-08 04:03:46
回答 2查看 134关注 0票数 0
代码语言:javascript
复制
class Port
{
private:
    char * brand;
    char style[20]; // i.e., tawny, ruby, vintage
    int bottles;
public:
    Port(const char * br = "none", const char * st = "none", int b = 0);
    Port(const Port & p); // copy constructor
    virtual ~Port() {delete[] brand; }
    Port & operator=(const Port & p);
    Port & operator+=(int b); // adds b to bottles
    Port & operator-=(int b); // subtracts b from bottles, if
    int BottleCount() const { return bottles; }
    virtual void Show() const;
    friend ostream & operator<<(ostream & os, const Port & p);
};



class VintagePort : public Port // style necessarily = "vintage"
{
private:
    char * nickname; // i.e., "The Noble" or "Old Velvet", etc.
    int year; // vintage year
public:
    VintagePort();
    VintagePort(const char * br, const char *st, int b, const char * nn, int y);
    VintagePort(const VintagePort & vp);
    ~VintagePort() { delete[]nickname;}
    VintagePort & operator=(const VintagePort & vp);
    virtual void Show() const;
    friend ostream & operator<<(ostream & os, const VintagePort & vp);
};

我必须解释为什么operator=()operator<<()不是虚拟的。我认为operator<<()不能是虚的,因为只有类方法可以是虚的,但我对operator=()一无所知。基类中的指针如何知道它必须使用哪一个operator=()

第二个问题是关于如何让operator<<()像虚拟方法一样工作,例如:

代码语言:javascript
复制
basicClass B;
inheritClass I;
basicClass *ptr;
ptr=&I;
std::cout << ptr // Here I'd like to use operator<<(std::ostream, inheritClass) 
EN

回答 2

Stack Overflow用户

发布于 2015-06-08 08:47:02

operator =不是虚拟的,因为它未标记为virtualoperator =的声明如下所示

代码语言:javascript
复制
//No virtual here
Port& operator =(const Port&);

但是,如果operator =是虚拟的,它将被这样声明

代码语言:javascript
复制
virtual Port& operator =(const Port&);
^^^^^^^ Virtual here!

因为operator =不是虚拟的,所以编译器在编译时使用静态链接。这意味着被调用的函数依赖于它所引用的变量的类型。考虑下面的代码:

代码语言:javascript
复制
VintagePort vp;

//Calls VintagePort::operator =(const VintagePort&)
vp = VintagePort();

Port* p = &vp;

//Calls Port::operator =(const Port&)
*p = Port();

VintagePort::operator =在作为VintagePort访问时调用,而Port::operator =在作为Port访问时调用。(实时示例here。)

要使operator <<的行为如同它是虚拟的一样,您必须在执行打印的类中声明一个虚拟成员函数。像这样的东西

代码语言:javascript
复制
//Inside Port
virtual void Print(std::ostream& os) const
{
    os << brand << ' ' << style << ' ' << bottles;
}

然后,在每个从Port派生的类(如VintagePort)中,您将覆盖该方法以同时打印该派生类的值。因此,对于VintagePort,您可以这样做

代码语言:javascript
复制
//Inside VintagePort
void Print(std::ostream& os) const
{
    //Make Port print first
    Port::Print(os);
    os << ' ' << nickname << ' ' << year;
}

然后,在operator <<中,您所要做的就是对参数调用Print方法。它看起来像这样:

代码语言:javascript
复制
std::ostream& operator <<(std::ostream& os, const Port& p)
{
    P.Print();
    return os;
}

另外,您不必为每个派生类重载operator <<,因为重载只需要Port类中的虚函数。

票数 1
EN

Stack Overflow用户

发布于 2015-06-08 04:58:49

这给人一种codereview的感觉,这不是它的用途--但不管怎样:

  • 不使用字符数组。使用std::string

class Port { private: std::string品牌;std::string style;//即tawny,ruby,vintage //... };

此外,一般来说,不要在对象合适的地方使用指针。如果您需要指针,请使用智能指针来清楚地表达其目的。

  • 如果你遵循前面的建议,就不需要定义:析构函数,复制/移动构造函数,而且--这涉及到你的问题--也不是赋值运算符。(特别是,没有必要重载不应该声明virtual的latter).

  • operator<<,因为它不是类成员。这是一个独立的函数,因为它是一个朋友,可以访问您的波特酒类的私有成员。

但是你可以在类的外部重载它。这就是通过将不同的重载设置为operator<<(ostream & os, const Port & p);operator<<(ostream & os, const VintagePort & p);.来直接执行的操作

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30697903

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档