c++ 在模板类中为一些模板参数隐藏纯虚方法以用于编译目的

x8diyxa7  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(116)

使用模板类,C++允许您添加无法为某些模板参数编译的方法,前提是您没有在具有错误模板参数的示例上调用该特定方法。

template<typename T>
class B 
{
public :
    int foo()  {return 5;}
    int bar()
    {
     T v;
     return v;
    }
};

int main(int argc, char * argv[])
{
    B<int> b1;
    b1.foo();
    b1.bar(); // this line compiles
    B<string> b2;
    b2.foo();
    //b2.bar(); this line won't compile
}

现在假设class B有一个基类,其中bar()是一个虚方法

template<typename T>
class A {
public :
    virtual int foo() =0;
    virtual int bar() =0;
};

template<typename T>
class B : public A<T>
{
public :
    int foo() override {return 5;}
    int bar() override
    {
     T v;
     return v;
    }
};

int main(int argc, char * argv[])
{
    B<int> b1;
    b1.foo();
    b1.bar();
    B<string> b2; // instanciation not allowed
    b2.foo();
}

这段代码无法编译。原因很清楚:B<string>派生自A<string>,它公开了一个bar()虚拟方法。
但是,实际上我并不打算调用bar(),只要示例化的类型是string。所以我想告诉编译器,A::bar()只存在于int模板类型中。
处理这个问题的最干净的方法是什么?

gg0vcinb

gg0vcinb1#

我不确定这是不是最好的处理方式,但是你可以通过显式的专门化来处理:

#include <string>

template<typename T>
class A {
public :
    virtual int foo() =0;
};

template <>
class A<int> {
public:
    virtual int foo() = 0;
    virtual int bar() = 0;
};

template<typename T>
class B : public A<T>
{
public :
    int foo() override {return 5;}
};

template <>
class B<int> : public A<int> {
public:
    int foo() override { return 5; }
    int bar() override { return 1; }
};

int main(int argc, char * argv[])
{
    B<int> b1;
    b1.foo();
    b1.bar();
    B<std::string> b2; // instanciation now allowed
    b2.foo();
}

我不确定这真的有多大的成就。特别是,使用继承的 * 通常 * 原因是允许您使用指向基类的(可能是智能的)指针来处理派生类的对象。但是在这种情况下,A<int>是一个与A<std::string>完全独立的类型,所以你不能有类似A *的集合,其中一些引用B<int>类型的对象,另一些引用B<std::string>类型的对象(等等),然后在这些派生对象上调用虚函数。
另一方面,你也可以有一个C<T>类,它也是从A<T>派生的,然后有一个A<T> *的集合,它可以指向B<T>C<T>(在整个T类型中是相同的),并调用所有这些类上的虚函数。

相关问题