Effective C++ 条款43

学习处理模板化基类里的名称

本节作者编写的意图在我看来可以总结成一句话,就是“如何定义并使用关于模板类的派生过程,如何处理派生过程出现的编译不通过问题”。

下面我们看一段说明性的代码:

#include<iostream>
using namespace std;

class object1
{
public:
    void get(){ cout << "object1"; }
    void out(){ cout << "out1"; }
};

class object2
{
public:
    void get(){ cout << "object2"; }
    void out(){ cout << "out2"; }
};

template <typename object>
class A
{
public :
    void func1()
    {
        object ob;
        ob.get();
    }
    void func2()
    {
        object ob;
        ob.out();
    }
};

int main()
{
    A<object1>a;
    a.func1();//调用object1中的get函数
    cout << endl;
    A<object2>b;
    b.func2();//调用object2中的out函数

}

由上面的代码可以看出template模板带给我们编程的优越性,它极大的提高了我们代码的利用率。可是好性能背后往往都会有一些牺牲,比如在多重继承中的编译问题。

如下代码:

#include<iostream>
using namespace std;

class object1
{
public:
    void get(){ cout << "object1"; }
    void out(){ cout << "out1"; }
};

class object2
{
public:
    void get(){ cout << "object2"; }
    void out(){ cout << "out2"; }
};

class object3
{
public:
    void out(){ cout << "out3"; }
};

template <typename object>
class A
{
public :
    void func1()
    {
        object ob;
        ob.get();
    }
    void func2()
    {
        object ob;
        ob.out();
    }
};

template<>
class A<object3>
{
public:
    void func2()
    {
        object3 ob;
        ob.out();
    }
};

template <typename object>
class B:public A<object>
{
public:
    void func3()
    {
        func1();
    }
};

以上代码,按照作者的意思是编译不通过,因为无法确定是否模板类template base class中有funct1()函数,我用的是vs2014编辑器,并没有出现这种问题。所以,不知道是不是微软开发大神完善了这个编译缺点。一句话,对于,vs2014来说该条款是无效的,欢迎大神指正。

至于,假设为什么无法编译,是因为有全特化模板的出现。如上对object3的全特化过程中并没有funct1()函数,这时如果编译器不进行阻止,在程序以后运行中就会崩溃。

按作者的意思,如果出现以上问题,可以通过以下三种手段解决,三种方式的用意就是告诉编译器,基类中拥有派生类所需的函数。让编译器进入基类进行寻找。而不是在没有寻找的前提下就编译报错。

第一种:

template <typename object>
class B:public A<object>
{
public:
    void func3()
    {
        this->func1();//加上this关键字
    }
};

第二种:

template <typename object>
class B:public A<object>
{
      using A<object>::func1;
public:
    void func3()
    {
        this->func1();//加上this关键字
    }
};

第三种:

template <typename object>
class B:public A<object>
{
public:
    void func3()
    {
        A<object>::func1();
    }
};

至于第三种,会关闭virtual绑定行为,慎用。

时间: 2024-10-11 06:23:40

Effective C++ 条款43的相关文章

More Effective C++ 条款35 让自己习惯于标准C++ 语言

(由于本书出版于1996年,因此当时的新特性现在来说可能已经习以为常,但现在重新了解反而会起到了解C++变迁的作用) 1. 1990年后C++的重要改变 1). 增加了新的语言特性:RTTI,namespaces,bool,关键词mutable和explicit,enums作为重载函数之自变量所引发的类型晋升转换,以及"在class 定义区内直接为整数型(intergral) const static class members设定初值"的能力. 2). 扩充了Templates的特性

effective c++ 条款4 make sure that objects are initialized before they are used

1 c++ 类的数据成员的初始化发生在构造函数前 class InitialData { public: int data1; int data2; InitialData(int a, int b) { data1 = a: //this is assignment data2 = b; //this is assignment } /* InitialData(int a, int b):data1(a),data2(b) //this is initial {} */ } 2 不同cpp文

More Effective C++ 条款34 如何在一个程序中结合C++和C

1. C++和C混合使用的前提之一就是编译器产生兼容的目标文件(.lib和.dll等).所谓"兼容",指的是编译器在"预编译器相依的特性上"一致,如int和double大小,参数压栈机制等,只有在这个基础上才能讨论结合使用C++和C模块的问题. 2. 在1的基础上,要结合使用C++和C的模块,主要有以下几点需要注意: 1). name mangling(名称重整) Name mangling是C++用于支持函数重载的机制,它对重载的函数名称进行一定改变,使得每个函数

Effective C++ 条款3 尽可能用const

1. const可被施加于任何作用域内的对象,函数参数,函数返回类型,成员函数本体.用const修饰指针,如果const出现在*之前,表明指针不能更改所指向的对象的内容,如果const出现在*之后,表明指针只能指向同一块内存.另外int const*p和const int*p含义相同.如果对象成员有普通指针,那么构造该类的一个const对象时,const修饰使得该指针只能指向同一块内存,但指针指向的内容可以改变. 2. 将某些东西声明为const可以帮助编译器侦测出错误用法. 3. 编译器强制实

effective c++ 条款13 use object to manage resources.

请求的系统资源需要最终还回系统,为了避免遗忘返还这个动作,可以利用析构函数在object销毁时自动调用的特点来实现. 简单说就是用object来管理资源. 以内存资源为例 class Investment {}; Investment* creatInvestment(){...} // factory function to produce investment object void main() { Investment* pInv = creatInvestment();//call t

effective c++ 条款3 use const whereever you can

1 const 传达的意思应该是这个变量是常量不能更改 2 const 在 * 左边表示数据是const,在右边表示指针是const // char greeting[] = "hello"; char* p = greeting; //const *: const data //* const: const pointer char const *p1 = greeting; // const data char * const p2 = greeting; // const poi

effective c++ 条款18 make interface easy to use correctly and hard to use incorrectly

举一个容易犯错的例子 class Date { private: int month; int day; int year; public: Date(int month,int day,int year) { this->month = month; ... } } //wrong example Date date(30,3,1995);//should be 3,30 Date date(2,30,1995);//should be 3,30 使用类型可避免这个问题 class Month

Effective C++ 条款44 将与参数无关的代码抽离template

1. template是节省时间和避免代码重复的有效方法,而且在将类模板(class template)具现化时,编译器只具现化那些被用到的成员函数,这更加节省了空间. 2. 正如两个函数存在代码重复时,倾向于把重复的代码抽出独立形成一个函数,然后让之前的函数调用这个函数,函数模板也可以这样,甚至类模板也可以采用相同的思想,例如,对于以下用于操作方矩阵的类模板: template<typename T,std::size_t n> //n是非类型参数 class SquareMatrix{ p

effective c++ 条款9 do not call virtual function in constructor or deconstructor

在构造函数中不要调用virtual函数,调用了也不会有预期的效果. 举个例子 class Transaction { public: Transaction() { log(); } virtual void log() =0; } class BusinessTransaction: public Transaction { public: virtual void log() { ;//log something here } } BusinessTransaction b_trx; b_t