C++ learning eighth

1) Learning of virtual inheritance and virtual base classes


using namespace std;
class Parent
{
    
    
public:
    int m_;
};
//何为虚继承和虚基类:用virtual继承父类,(所有相关的类都必须virtual父类才可以),则叫虚继承;
//被虚继承的父类则就叫虚基类,(父类没有任何改变,只是叫法不同而已);
//虚继承对子类没有任何影响,主要是影响的孙子类,为了孙子也是拼了。所谓前人栽树,后人乘凉,是也!
class A : virtual public Parent //A和B都得虚继承才可以
{
    
    
};

class B : virtual public Parent
{
    
    
};

class C :public A, public B
{
    
    
};

int main()
{
    
    
    C c;
    c.m_ = 20; //如果不是虚继承,这条语句会出现访问不明确
    cout << c.m_ << endl;
    return 0;
}

2) How to use member function pointers of classes

class A
{
    
    
public:
    A() :m_(23) {
    
     cout << "A constructor--" << endl; }
    void func(int aa)
    {
    
    
        cout << "m_ is: "<<m_ + aa << endl;
    }
private:
    int m_;
};

int main()
{
    
    
    A a1;
    void(A::*fptr)(int); //定义类的成员函数指针
    fptr = &A::func; //给类的成员函数指针赋值,有真正的地址
    //如果使用类的成员函数指针,则必须有类对象,用类对象调用;
    (a1.*fptr)(10);//利用类的成员函数指针调用类的成员函数
    return 0;
}

// fun(2.3f); 或 fun(2.3F); 调用形参为 float 的函数
// fun(2.3); 调用形参为 double 的函数,因为C/C++浮点型数据默认是 double 型

3) Template functions, including the use of template parameters and non-template parameters.
The use of function templates:


using namespace std;
// 模板和泛型编程
// 所谓泛型编程,是独立于任何特定类型的编程方式;
// 模板是泛型编程的基础;
// 模板是将类型定义为参数的程序方式;
// 在模板参数列表里,除了可以定义【类型参数】外,还可以定义【非类型参数】;重点!
// 非类型参数不可以用typename/class来修饰,必须用具体的类型来修饰
// 非类型参数必须是常量表达式,因为在编译阶段就得确认具体数值;
// 函数模板通常放在".h"中;
// 在头文件定义函数模板,在多个.cpp文件包含,不会造成重定义,如果是普通文件就会造成重定义;

//类型模板参数
template<typename T> //里面的参数叫模板参数列表
T add(T a, T b)
{
    
    
    return a + b;
}

//非类型模板参数
template<int a,int b>
int add1()
{
    
    
    return a + b;
}

//既有类型模板参数,又有非类型模板参数
template<int a, int b, typename T> //定义顺序和调用顺序必须一致,否则编译错误
int add2(T mm)
{
    
    
    return (int)mm + a + b;
}

int main()
{
    
    
    int ret = add<int>(4, 5); //类型模板参数调用方法
    ret = add1<3, 2>();//非类型模板参数调用方法! 用尖括号里面的数值给非类型参数传递数值
    ret = add2<10,20,int>(3);//既有类型模板参数,又有非类型模板参数的调用方法
    cout << ret << endl;
    return 0;
}

4) Class template definition and use



4.1)(类模板的类型参数使用)
template<class T>
class MyVector
{
    
    
public:
    MyVector(T a);
    typedef T* iterator; //迭代器
    MyVector& operator=(const MyVector&);//赋值运算符重载;在类模板内部使用模板名可以不写模板参数;
    //MyVector<T>& operator&(const MyVector<T>&);
    iterator begin();
    iterator end();
    void func(void);
    T a_;
};

//类模板的构造函数
template<class T>
MyVector<T>::MyVector(T a):a_(a)
{
    
    
    cout << "MyVector constructor a_: " << a_ << endl; 
}

//类模板的类外定义成员函数,把【模板参数名】列出来
template<class T>
void MyVector<T>::func(void) //void MyVector::func(void)这样写是错误的,MyVector是类模板名,不是类名
{
    
    

}

//模板类名字的使用,如下所示,必须在类模板中添加"<T>",使之成为【类名】;
template<class T>
MyVector<T>& MyVector<T>::operator=(const MyVector<T>&) //类模板的赋值运算符重载
{
    
    
    return *this;
}

主函数调用如下:
MyVector<int> vec(23); //如果调用的话,编译器会生成一个具体的类;
MyVector<double> vec1(23);//又生成另外一个类对象

4.2)(类模板的非类型参数使用)
//类模板的非类型参数使用方法
template<class T,int N = 4> //默认模板参数只在声明中体现
class Test
{
    
    
public:
    void printMsg(T tmp);
};

template<class T, int N> //如果int改为浮点型,则编译出错
void Test<T,N>::printMsg(T tmp)
{
    
    
    cout << N + tmp << endl;
}

int main()
{
    
    
    Test<int> t1; //使用默认值4
    Test<int,5> t2; //从新设置非类型模板参数
    t1.printMsg(5);
    t2.printMsg(5);
    return 0;
}

5) Typename usage occasions, analysis of default template parameters and interesting writing methods



(1) 定义模板参数,如:template<typename T>
(2) 修饰类型,如下代码:
using namespace std;

template<class T>
class MyVector
{
    
    
public:
    MyVector(T a);
    typedef T* iterator; //迭代器
    MyVector& operator=(const MyVector&);//赋值运算符重载;在类模板内部使用模板名可以不写模板参数;
    iterator begin();
    iterator end();
    void func(void);
    T a_;
};

//类模板的构造函数
template<class T>
MyVector<T>::MyVector(T a):a_(a)
{
    
    
    cout << "MyVector constructor a_: " << a_ << endl; 
}

//类模板的类外定义成员函数,把【模板参数名】列出来
template<class T>
void MyVector<T>::func(void) //void MyVector::func(void)这样写是错误的,MyVector是类模板名,不是类名
{
    
    

}

//模板类名字的使用,如下所示,必须在类模板中添加"<T>",使之成为【类名】;
template<class T>
MyVector<T>& MyVector<T>::operator=(const MyVector<T>&) //类模板的赋值运算符重载
{
    
    
    return *this;
}

//使用类的类型成员,iterator是一个类型
//typename这里的目的:就是告诉编译器"iterator"是一个类型,不是类的静态成员变量;
template<class T>
typename MyVector<T>::iterator MyVector<T>::begin() //iterator MyVector<T>::begin()这样写是不对的,
{
    
    

}

template<class T>
typename MyVector<T>::iterator MyVector<T>::end()
{
    
    

}

6) Function pointers are used as parameters of other functions

typedef int(*fptr)(int, int);

int func(int a, int b)
{
    
    
    return a + b;
}
void test(int a, int b, fptr fn)
{
    
    
    cout << fn(a, b) << endl;
}

int main()
{
    
    
    test(2, 4, func);
    return 0;
}

7) Functor (class of callable object) //Note: In this case, both function template and class template can be called

int func(int a, int b)
{
    
    
    return a + b;
}

template<typename T, typename F>
void test(T a, T b, F fn)
{
    
    
    cout << fn(a, b) << endl;
}

class A
{
    
    
public:
    A()
    {
    
    
        cout << "constructor" << endl;
    }
    int operator()(int a, int b)const
    {
    
    
        return a + b;
    }
};

int main()
{
    
    
    test(2, 4, func); 
    A a;
    test(2, 7, a);
    return 0;
}

8) Default type template parameters and default non-type parameters

template<class T = int> //默认类型模板参数
class A
{
    
    
public:
    A(T val):val_(val){
    
    }
    void printMsg(void) {
    
     cout << "val_is: " << val_ << endl; }
private:
    T val_;
};

int main() 
{
    
    
    A<> a1(10); //使用的是默认类型模板参数
    a1.printMsg();

    A<double> a2(2.9);
    a2.printMsg(); //使用的是double类型模板参数

    return 0;
}

默认非类型模板参数
template<int N = 5> //模板类的非类型默认参数
class A
{
    
    
public:
    int arr[N];
private:
};

int main() 
{
    
    
    A<> a1;//使用的是非类型默认参数
    A<10>a2; //定义10个数组元素
    return 0;
}


Guess you like

Origin blog.csdn.net/qq_30143193/article/details/132420850