我正在实现一个观察者模式作为模板,并希望一个类附加不同的侦听器类型。问题是,使用不同类型多次在单个类中使用相同的模板似乎是不可能的。据我所知,它应该是可能的,因为方法名称无论如何都会有不同的类型,所以它们应该被修改成不同的名称。然而,我得到的错误不是在链接时,而是在编译时,所以我想知道我做错了什么或者根本不可能。
为了证明这个问题,我写了一个SSCE:
#include <iostream>
#include <string>
template<typename T>
class Comparator
{
public:
Comparator(void) { mCounter = 0; };
virtual ~Comparator(void) {};
bool equals(T oFirst, T oSecond)
{
mCounter++;
if(oFirst != oSecond)
return false;
return true;
}
int getCounter(void)
{
return mCounter;
}
private:
int mCounter;
};
class TestClass :
public Comparator<int>,
public Comparator<void *>
{
public:
TestClass(void) {};
virtual ~TestClass(void) {};
};
int main(int argc, char *argv[])
{
TestClass t1;
TestClass *t2 = &t1;
TestClass *t3 = new TestClass();
int v1 = 1;
int v2 = 2;
bool b = t1.equals(v1, v2);
std::cout << b << std::endl;
std::cout << t1.equals(&t1, &t2) << std::endl;
std::cout << t1.getCounter() << std::endl;
delete t3;
return 0;
}
当我用gcc(使用Cx11选项)编译它时,我收到以下错误:
||=== Build: Debug in CPPMingW (compiler: GNU GCC Compiler) ===|
D:\src\c\Tests\CPPMingW\main.cpp||In function 'int main(int, char**)':|
D:\src\c\Tests\CPPMingW\main.cpp|38|error: request for member 'equals' is ambiguous|
D:\src\c\Tests\CPPMingW\main.cpp|12|note: candidates are: bool Comparator<T>::equals(T, T) [with T = void*]|
D:\src\c\Tests\CPPMingW\main.cpp|12|note: bool Comparator<T>::equals(T, T) [with T = int]|
D:\src\c\Tests\CPPMingW\main.cpp|38|error: expected primary-expression before 'int'|
D:\src\c\Tests\CPPMingW\main.cpp|38|error: expected ';' before 'int'|
D:\src\c\Tests\CPPMingW\main.cpp|39|error: request for member 'equals' is ambiguous|
D:\src\c\Tests\CPPMingW\main.cpp|12|note: candidates are: bool Comparator<T>::equals(T, T) [with T = void*]|
D:\src\c\Tests\CPPMingW\main.cpp|12|note: bool Comparator<T>::equals(T, T) [with T = int]|
D:\src\c\Tests\CPPMingW\main.cpp|35|warning: unused variable 'v1' [-Wunused-variable]|
D:\src\c\Tests\CPPMingW\main.cpp|36|warning: unused variable 'v2' [-Wunused-variable]|
||=== Build failed: 4 error(s), 2 warning(s) (0 minute(s), 1 second(s)) ===|
在这个例子中,我并不真正理解为什么它应该是不明确的,因为在两个调用中,数据类型都是明确定义的,并且与其他模板特化完全不同。我希望来自getCounter()
的errof,因为这实际上是不可确定的。
答案 0 :(得分:4)
您希望基类中的equals
参与重载解析,就好像它们都是在派生类中定义的那样,但不幸的是它不会那样工作(我不知道为什么不)。
您可以显式调用所需的equals
版本:
t1.Comparator<int>::equals(v1, v2);
或者您可以在派生类(公共部分)中添加它:
using Comparator<int>::equals;
using Comparator<void*>::equals;
哪个应该允许基类的2等于函数执行标准重载决策。您也可以通过在派生类中编写equals
。
请注意:Comparator<int>
和Comparator<void*>
是完全独立的类。他们彼此都不知道。如果它们不是模板但也有不同的名称,则表现相同。