【发布时间】:2018-04-10 21:10:27
【问题描述】:
我有一个对我来说表现奇怪的代码示例。 通过 C++ 中的继承,可以使用纯虚函数(也称为接口)声明指向基类的指针数组,并在其上调用派生成员函数;
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
看起来我可以对 operator
【问题讨论】:
-
你真的认为所有的垂直空格都增加了代码的可读性吗?
-
“问题是它为什么会这样?”因为这就是您对其进行编程的目的。模板化的
operator<<不是虚拟的。 -
@NeilButterworth 这只是我喜欢的代码风格。没有在规则中找到任何关于这种代码格式的建议。
-
@NeilButterworth 与大多数程序员相比,我更喜欢垂直空白(尽管我承认没有这么多)。不过,它仍然是可读的,除非 SO 为问题和答案制定了所需的编码风格,否则不值得抱怨。
-
@NeilButterworth 缩进都排成一行,垂直空格的使用一致。实际上,我发现不必要地使用宽字符串更让人分心,因为我很少看到这种语法(因为宽字符串不是很便携,你通常应该更喜欢显式的 Unicode 类型)。
标签: c++ inheritance virtual overriding