我知道这看起来像一个愚蠢的问题,但在C ++中使用带有模板的面向对象的东西真的很麻烦。 例如,Foo是基类:
template <typename T>
class Foo {
public:
virtual void Method1() { }
virtual void Method1(int a) { }
virtual void Method2() { }
virtual void Method2(int a) { }
//... lots of other methods
};
是否有类似的东西:
template <typename T>
class Bar : public Foo<T> {
public:
using Foo<T>::*; //redefine all inherited methods from Foo
virtual void Method1(int a) { }
virtual void Method2(int a) { }
//other methods overloading..
};
而不是:
template <typename T>
class Bar : public Foo<T> {
public:
using Foo<T>::Method1
using Foo<T>::Method2
//... lots of other methods
virtual void Method1(int a) { }
virtual void Method2(int a) { }
//other methods overloading..
};
所以我们可以这样做:
int main() {
Bar<int> b;
b.Method1();
b.Method2();
//... lots of other methods
//This obviously works without the 'using' keyword:
Foo<int>* f = &b;
f->Method1();
f->Method2();
//etc
return 0;
}
答案 0 :(得分:3)
不,没有类似的功能,但通常不需要。基本继承机制已经提供了您打算使用using
做什么。
如果派生类中的重载隐藏了基类中的方法,或者您想要更改访问模式, 需要才能使用using
:
class A {
void f() {}
public:
void g(int) {}
void h(int) {}
};
struct B : A {
using A::f; // make f public
void g(double) {}
using A::g; // otherwise A::g is hidden by the overload
// using A::h isn't needed
};
请注意,您仍然可以通过A::h()
实例调用B
,因为没有任何内容隐藏它。
答案 1 :(得分:0)
没有。模板特化是不与一般模板继承或以其他方式相关的单独类型。你应该确保它们具有相同的隐式接口,而C ++并不能使它变得特别容易。
另请参阅最近的这个问题,这很可能是您正在寻找的问题。 subclass as specialization - ie: adding a method in the specialization
答案 2 :(得分:0)
<强> 1。隐藏的是什么
我担心你的小例子有问题,我怀疑你的问题出在Hiding
。
让我们来说明Hiding
是第一个:
struct Base { void foo(int) { std::cout << "Base" << std::endl; } };
struct Derived: Base { void foo(float) { std::cout << "Derived" << std::endl; } };
int main(int, char* argv[])
{
Derived d;
int integer = 1;
float floating = 2;
d.foo(floating); // outputs "Derived" as expected
d.foo(integer); // outputs "Derived" too UhOh ?
}
这个问题被称为Hiding
,这是编译时名称解析的问题。问题是在应用重载规则选择“正确”方法之前,编译器首先需要编译要考虑的方法集。为此,它将查看最专业的范围,然后一次向外扩展一个范围,直到找到它正在寻找的名称。不幸的是(出于效率原因,我猜),一旦找到具有名称的函数,它就会停止。
所以这里发生的是:
foo
中查找名为Derived
的方法:{ void Derived::foo(float) }
然后停止......因此,在尝试解析foo
int
参数时,它会选择到目前为止看到的唯一方法,这可能有点令人惊讶。
你是正确的,你可以用using
关键字来胜过它,它带来了另一个范围的名称,以便编译器考虑它们。如果我在using Base::foo;
定义中添加Derived
,编译器将执行:
foo
中查找名为Derived
的方法:{ void Derived::foo(float) }
+ using
foo
中添加名为Base
的方法:{ void Derived::foo(float), void Base::foo(int) }
因此,你得到了你所希望的。
<强> 2。如何重新定义方法
既然您知道Hiding
是什么,以及如何规避它,我想借此机会解决您的示例缺陷。
你不应该重新定义这样的方法:
struct Base { void foo(int) const { std::cout << "Base" << std::endl; } };
struct Derived: Base { void foo(int) const { std::cout << "Derived" << std::endl; } };
这里的问题是它只是Hiding
而且可能会令人惊讶。
void fooize(const Base& b) { b.foo(); }
int main(int argc, char* argv[])
{
Derived d;
d.foo(); // output "Derived"
fooize(d); // output "Base"
}
如果您想重新定义,则需要使用virtual
关键字。然后你会用这种方式纠正你的课程:
struct Base
{
virtual ~Base() {} // Polymorphism means virtual destructor
virtual foo(int) const { std::cout << "Base" << std::endl; }
};
struct Derived: Base
{
virtual ~Derived() {} // Not necessary, but sweet reminder
virtual foo(int) const; // virtual not necessary, but a sweet reminder again :)
};
然后它将按预期工作。
第3。多态烹饪书
virtual
virtual Destructor
(因为它将被重新定义)令人遗憾的是(对于Composition)C ++中没有“委托”概念,但是我们必须处理我们已经给出的卡片。
最后要注意的是:如果该类有很多方法......它可能会受益于重新设计(请参阅std::string
以获取不应该做的示例)。