gpt4 book ai didi

c++ - 为什么这个 C++ 继承代码示例的行为是这样的

转载 作者:行者123 更新时间:2023-11-30 03:24:20 25 4
gpt4 key购买 nike

我有一个代码示例,它对我来说很奇怪。通过 C++ 中的继承,可以使用纯虚函数(也称为接口(interface))声明指向基类的指针数组,并在其上调用派生成员函数;

class Base {

public:

virtual void call() = 0;

};

class Derived1 : public Base {

public:

void call() override final {

std::wcout << L"derived 1" << std::endl;

}

};

class Derived2 : public Base {

public:

void call() override final {

std::wcout << L"derived 2" << std::endl;

}

};

int main() {

Base* b[2];

b[0] = new Derived1;
b[1] = new Derived2;

for (int i = 0; i < 2; ++i) {

b[i]->call();

}

return 0;

}

给出:

derived 1
derived 2

正如计划的那样。但是当我尝试遵循代码示例时,它让我有点困惑:

class Base {

public:

virtual Base* print() = 0;

template<typename T>
Base& operator<<(const T &_val) {

std::wcout << L" d0 << " << _val;
return *this;

}

};

class Derived1 : public Base {

public:

Derived1* print() override final {

return this;

}

template<typename T>
Derived1& operator<<(const T &_val) {

std::wcout << L" d1 << " << _val;
return *this;

}

};

class Derived2 : public Base {

public:

Derived2* print() override final {

return this;

}

template<typename T>
Derived2& operator<<(const T &_val) {

std::wcout << L" d2 << " << _val;
return *this;

}

};

int main() {

Base* b[2];

b[0] = new Derived1;
b[1] = new Derived2;

for (int i = 0; i < 2; ++i) {

std::wcout << typeid(*b[i]->print()).name();
*b[i]->print() << 7 << 7;
std::wcout << std::endl;

}

return 0;

}

输出是:

8Derived1 d0 << 7 d0 << 7
8Derived2 d0 << 7 d0 << 7

这意味着只有 Base 的运算符<< 被调用(但 prints() 返回类型似乎是正确的)。

问题是为什么它会这样

更新:


似乎我需要这里没有虚函数的静态多态性。但这怎么可能实现呢?我需要一组不同的派生类来在 operator<< 中对任何数据类型执行操作。UPD2:


看起来我可以对 operator<< 参数使用类型删除。但是我怎样才能在派生的 operator<< 中恢复类型呢? (例如,如果我建议使用 boost::any)

最佳答案

你的 operator << ()不是虚拟的,因此,如果您调用基类指针的此运算符,将始终调用基类实现。

那是因为它是模板方法,模板方法不能是virtual (参见 Can a C++ class member function template be virtual?)。

解决方案是编写虚拟专用 operator << ()对于每种支持的数据类型(如果您真的希望它们在继承的类之间有所不同)。

修改后的代码:

class Base {

public:

virtual Base* print() = 0;

virtual Base& operator<<( int _val ) = 0;

};

class Derived1 : public Base {

public:

Derived1* print() override final {

return this;

}

Base& operator<<( int _val ) override final {

std::wcout << L" d1 << " << _val;
return *this;

}

};

class Derived2 : public Base {

public:

Derived2* print() override final {

return this;

}

Base& operator<<( int _val ) override final {

std::wcout << L" d2 << " << _val;
return *this;

}

};

int main() {

Base* b[2];

b[0] = new Derived1;
b[1] = new Derived2;

for (int i = 0; i < 2; ++i) {

std::wcout << typeid(*b[i]->print()).name();
*b[i]->print() << 7 << 7;
std::wcout << std::endl;

}

return 0;

}

另一种方法是,仅通过类层次结构(此处为类名)实现不同的部分,并使用模板运算符进行通用调用。

#include <iostream>
#include <string>

class Base {

public:

virtual Base* print() = 0;
virtual const wchar_t* className() const = 0;

template<typename T>
Base& operator<<(const T &_val) {

std::wcout << L" " << className() << L" << " << L" << " << _val;
return *this;

}

};

class Derived1 : public Base {

public:
const wchar_t* className() const override final { return L"d1"; }

Derived1* print() override final {

return this;

}

};

class Derived2 : public Base {

public:
const wchar_t* className() const override final { return L"d2"; }

Derived2* print() override final {

return this;

}

};

int main() {

Base* b[2];

b[0] = new Derived1;
b[1] = new Derived2;

for (int i = 0; i < 2; ++i) {

std::wcout << typeid(*b[i]->print()).name();
*b[i]->print() << 7 << 7;
std::wcout << std::endl;

}

return 0;

}

最后一种方法是根据类类型进行 RTTI 转换,并调用专门的 operator << ()根据类类型。

#include <iostream>

class Derived1;
class Derived2;

class Base {

public:

virtual Base* print() = 0;


};

class Derived1 : public Base {

public:

Derived1* print() override final {

return this;

}

template<typename T>
Derived1& operator<<(const T &_val) {

std::wcout << L" d1 << " << _val;
return *this;

}

};

class Derived2 : public Base {

public:

Derived2* print() override final {

return this;

}

template<typename T>
Derived2& operator<<(const T &_val) {

std::wcout << L" d2 << " << _val;
return *this;

}

};

template<typename T>
Base& operator<<( Base& _base, const T &_val) {

if( typeid( _base ) == typeid( Derived1 ))
return dynamic_cast<Derived1*>(&_base)->operator << (_val);
else
return dynamic_cast<Derived2*>(&_base)->operator << (_val);
}

int main() {

Base* b[2];

b[0] = new Derived1;
b[1] = new Derived2;

for (int i = 0; i < 2; ++i) {

std::wcout << typeid(*b[i]->print()).name();
*b[i]->print() << 7 << 7;
std::wcout << std::endl;

}

return 0;

}

关于c++ - 为什么这个 C++ 继承代码示例的行为是这样的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49762893/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com