为什么C++更喜欢这个模板方法而不是方法重载
Why does C++ prefer this template method to a method overload?
假设我有两个类,第一个用于编写基元类型(bool
,int
,float
等),第二个扩展第一个类以编写复杂类型:
struct Writer {
virtual void Write(int value) = 0;
};
struct ComplexWriter : public Writer {
template <typename TValue> void Write(const TValue &value) {
boost::any any(value);
Write(any);
}
//virtual void Write(int value) = 0; // see question below
virtual void Write(const boost::any &any) = 0;
};
这个想法是,如果有人调用myWriter.Write(someIntValue);
,int 重载将优先于模板化方法。
相反,我的编译器(Visual C++ 11.0 RC)总是选择模板方法。例如,以下代码片段将Wrote any
打印到控制台:
struct ComplexWriterImpl : public ComplexWriter {
virtual void Write(int value) { std::cout << "Wrote an int"; }
virtual void Write(const boost::any &any) { std::cout << "Wrote any"; }
};
void TestWriter(ComplexWriter &writer) {
int x = 0;
writer.Write(x);
}
int main() {
ComplexWriterImpl writer;
TestWriter(writer);
}
当我在 ComplexWriter
类中声明 Write(int)
方法时,行为也会突然改变(请参阅第一个代码段中注释掉的行)。然后,它将Wrote an int
打印到控制台。
这是我的编译器应该表现的方式吗?C++标准是否明确规定,只有在同一类(而不是基类)中定义的重载才应优先于模板化方法?
问题是,在你调用writer.Write(x)
时,编译器看到的是ComplexWriter
而不是ComplexWriterImpl
,所以它只知道ComplexWriter
中定义的函数——模板函数和boost::any
函数。
ComplexWriter
不包含任何接受int
的虚函数,所以它无法调用ComplexWriterImpl
中定义的int重载
当您将虚拟重载添加到 ComplexWriter
类时,编译器会意识到 ComplexWriter
类中存在整数重载,因此在 ComplexWriterImpl
中调用它的实现
:现在您已经编辑了ComplexWriter和Writer之间的继承,我为您提供了更完整的解释:
当您创建一个子类并在其中定义一个函数时,基类中该名称的所有函数都将被隐藏,无论它们的参数类型如何。
我相信您可以使用 using 关键字来解决此问题:
struct ComplexWriter : public Writer {
template <typename TValue> void Write(const TValue &value) {
boost::any any(value);
Write(any);
}
using Writer::Write;
virtual void Write(const boost::any &any) = 0;
};
有关更多详细信息,请参阅此常见问题条目:http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9
编辑2:只是为了确认这确实解决了您的问题:http://ideone.com/LRb5a
当您通过ComplexWriter
"接口"访问对象时,编译器将尝试使用该类中的定义解析函数调用以Write(int)
。 如果它不能这样做,它将考虑基类。
在本例中,您有两个候选项:Write(any)
和模板化版本。 由于此时没有明确的Write(int)
可用,因此必须在这两个选项之间进行选择。 Write(any)
需要隐式转换,而模板化版本不需要,因此调用模板化版本(反过来调用Write(any)
)。
要使Writer
中的Write(int)
可用,请导入Writer::Write
函数:
class ComplexWriter : public Writer
{
using Writer::Write;
// rest is as before
};
- C++:涉及继承和"using"时的方法重载
- 如何让编译器在C++中更喜欢常量方法重载?
- 为什么方法重载或枚举标志定义会触发 gcc7.2 编译器警告?
- C++模板方法重载和具有多态性的类访问
- 基于方法重载类
- 方法重载 C++ -> 只有一个方法调用
- 如何使用 SFINAE 禁用方法重载集?
- 使用类别方法重载 NSDecimalNumber 上的算术运算符
- C++继承和方法重载混淆
- 多态性和方法重载在C++中几乎是一样的
- 了解方法重载规则
- c++编译错误涉及方法重载的2个模板函数
- Qt/Qml 和方法重载
- 参数或方法重载的幻数
- 为什么C++更喜欢这个模板方法而不是方法重载
- C++方法重载
- 在C++中使用非友元方法重载 I/O 运算符 |&istream 和 &ostream 函数
- 插入方法重载
- 函数重载和方法重载之间的区别
- 正在解决跨基类的虚拟方法重载