-
如果使用私有或者保护派生导致基类公有成员无法作为派生类的数据在类的外部访问,可以通过using的方法重定义数据访问权限特征 公有继承 保护继承 私有继承 公有成员变成 派生类公有成员 派生类保护成员 派生类私有成员 保护成员变成 派生类保护成员 派生类保护成员 派生类私有成员 私有成员变成 只能通过基类接口访问 只能通过基类接口访问 只能通过基类接口访问 能否隐式向上转换 是 是(只能在派生类中) 是 class Base { private: int a = 0; protected: int b = 0; public: int c = 0; }; class Son1 :public Base { void Fun1() { //this->a = 0;X this->b = 0; this->c = 0; } };
-
派生类构造函数可以通过初始化列表来调用基类的构造函数(可以是默认复制构造函数),如果没有调用基类的构造函数,则派生类的构造函数会隐式的调用基类的无参构造函数:
#include<cstring> #include<iostream> class Base { private: int a = 0; protected: int b = 0; public: int c = 0; Base(int baseA, int baseB, int baseC) :a(baseA), b(baseB), c(baseC) {}; }; class Son :public Base { int d; void Fun1() { //this->a = 0; this->b = 0; this->c = 0; } Son(int baseA, int baseB, int baseC, int baseD) :Base(baseA, baseB, baseC), d(baseD) {}; Son(Base base, int baseD) :Base(base), d(baseD) {}; }; int main() { return 0; }
-
virtual使用:
- 修饰类中的成员函数,如果基类中的的成员函数使用类virtual,则派生类可以重写基类的该成员函数
- 如果定义了基类的指针或者引用,并且该指针和引用使用派生类构造或者赋值,如果调用一个基类和派生类都有的函数,如果基类同名函数没有被virtual修饰,则会调用基类的函数,否则调用派生类的函数。
- 当有数据在基类构造函数使用new运算符创建出来时,基类最好使用虚析构函数,以免上述的引用和指针在程序结束时调用基类的析构函数。
- 析构函数不能被继承。
- 针对部分对象子类在某相同的功能上实现效果的巨大差异,基类可以定义一个不实现其作用的虚函数,即纯虚函数,此函数在虚函数基础上在函数声明末尾加上 = 0,一旦类定义了纯虚函数,则这个类被称为抽象类;
#include<cstring> #include<iostream> class Food { private: static const bool CanEat = true; protected: enum class Color { kRed, kYellow, kGreen, kBlue, kPink }; enum class Teste { kSour, kSweet, kBitter, kHot, ksalty }; virtual bool ShowCanEat() { return CanEat; } public: virtual Color ShowColor() = 0; virtual Teste ShowTest() = 0; friend std::ostream& operator<<(std::ostream& os, const Color& color) { os << (int)color; return os; } friend std::ostream& operator<<(std::ostream& os, const Teste& teste) { os << (int)teste; return os; } }; class Fruit : public Food { public: Color ShowColor() { return Color::kYellow; } virtual bool ShowCanEat() { return Food::ShowCanEat(); } virtual Teste ShowTest() { return Teste::kSweet; } }; class Apple : public Fruit { Color ShowColor() { return Color::kGreen; } virtual Teste ShowTest() { return Teste::kHot; } }; int main() { Apple pear = Apple(); Fruit* ptrApple = &pear; std::cout << ptrApple->ShowColor() << std::endl; std::cout << ptrApple->ShowTest() << std::endl; return 0; }
2 3
#define _CRT_SECURE_NO_WARNINGS 1 #include<cstring> #include<iostream> class baseDMA { private: char* label; int rating; public: baseDMA(const char* l = "null", int r = 0) { label = new char[std::strlen(l) + 1]; std::strcpy(label, l); rating = r; } baseDMA(const baseDMA& rs) :baseDMA(rs.label, rs.rating) { ; } baseDMA& operator=(const baseDMA& rs) { if (this == &rs) return*this; delete[] label; label = new char[std::strlen(rs.label) + 1]; std::strcpy(label, rs.label); rating = rs.rating; return *this; } virtual ~baseDMA() { delete[] label; } }; class hasDMA : public baseDMA { private: char* style; public: hasDMA(const hasDMA& hs) :baseDMA(hs) { style = new char[std::strlen(hs.style) + 1]; std::strcpy(style, hs.style); } hasDMA& operator=(const hasDMA& hs) { if (this == &hs) return *this; baseDMA::operator=(hs);//如果使用*this=hs会导致编译器递归调用hasDMA的赋值运算符 delete[] style; style = new char[std::strlen(hs.style) + 1]; std::strcpy(style, hs.style); return *this; } }; int main() { return 0; }
-
虚继承P453
-
类模板,注意template中的typename和class并没有实际意义上的区别,而且template还可以添加参数,而且参数可以提供默认值。CPP允许部分具体化,如设置部分类型参数类指针类型,整形等
#include<iostream> //template<class TYPE1,typename TYPE2,int n> template<class ClassType = int> class Stack { private: enum { SIZE = 10 }; int stackSize; ClassType* items; int top; public: explicit Stack(int ss = SIZE); Stack(const Stack& st); ~Stack() { delete[] items; } bool IsEmpty() { return top == 0; }; bool IsFull() { return top == stackSize; }; bool Push(const ClassType& item); bool Pop(ClassType& item); Stack& operator=(const Stack& st); }; template<> class Stack<double> { private: int a = 0; }; template<class ClassType> Stack<ClassType>::Stack(int ss) :stackSize(ss), top(0) { items = new ClassType[stackSize]; } template<class ClassType> bool Stack<ClassType>::Push(const ClassType& item) { if (top < stackSize) { items[top++] = item; return true; } else return false; } template<class ClassType> bool Stack<ClassType>::Pop(ClassType& item) { if (top > 0) { item = items[--top]; return true; } else return false; } template<class ClassType> Stack<ClassType>& Stack<ClassType>::operator=(const Stack<ClassType>& st) { if (this == &st) return *this; delete[] items; stackSize = st.stackSize; top = st.top; items = new ClassType[stackSize]; for (int i = 0; i < top; ++i) { items[i] = st.items[i]; } return *this; } template<class ClassType> Stack<ClassType>::Stack(const Stack& st) { stackSize = st.stackSize; top = st.top; items = new ClassType[stackSize]; for (int i = 0; i < top; ++i) { items[i] = st.items[i]; } } template<class T1,class T2> class Pair{}; template<class T1> class Pair<T1, int>{}; template<class T1,class T2> class Pair<T1*, T2*> {}; int main() { Stack<int> st1; Stack<> st2; return 0; }
-
CPP可以使用成员模板,即在类中的数据成员或者函数成员上方创建模板
#include<iostream> template<class T> class beta { private: template<typename V> class hold { private: V val; public: hold(V v = 0) :val(v) {}; void show() const { std::cout << val << std::endl; } V Value() const { return val; } }; hold<T> q; hold<int> n; public: beta(T t, int i) :q(t), n(i) {}; template<typename U> U blab(U u, T t) { return (n.Value() + q.Value()) * u / t; } void Show() const { q.show(); n.show(); } }; int main() { beta<double> guy{ 3.5,3 }; guy.Show(); std::cout << guy.blab(10, 2.3) << std::endl; std::cout << guy.blab(10.0, 2.3) << std::endl; }
若需要在外部定义的话,上面代码相当于下面的代码:
#include<iostream> template<class T> class beta { private: template<typename V> class hold; hold<T> q; hold<int> n; public: beta(T t, int i) :q(t), n(i) {}; template<typename U> U blab(U u, T t); void Show() const { q.show(); n.show(); } }; template<class T> template<typename V> class beta<T>::hold { private: V val; public: hold(V v=0):val(v){} void show()const { std::cout << val << std::endl; } V Value() const { return val; } }; template<class T> template<typename U> U beta<T>::blab(U u, T t) { return (n.Value() + q.Value()) * u / t; } int main() { beta<double> guy{ 3.5,3 }; guy.Show(); std::cout << guy.blab(10, 2.3) << std::endl; std::cout << guy.blab(10.0, 2.3) << std::endl; }
3.5 3 28 28.2609
-
如果类中需要一个类似于需要未知的模板类作为使用,可以作以下定义:
#include<iostream> template<class ClassType> class Stack { private: enum { SIZE = 10 }; int stackSize; ClassType* items; int top; public: explicit Stack(int ss = SIZE); Stack(const Stack& st); ~Stack() { delete[] items; } bool IsEmpty() { return top == 0; }; bool IsFull() { return top == stackSize; }; bool Push(const ClassType& item); bool Pop(ClassType& item); Stack& operator=(const Stack& st); }; template<class ClassType> Stack<ClassType>::Stack(int ss) :stackSize(ss), top(0) { items = new ClassType[stackSize]; } template<class ClassType> bool Stack<ClassType>::Push(const ClassType& item) { if (top < stackSize) { items[top++] = item; return true; } else return false; } template<class ClassType> bool Stack<ClassType>::Pop(ClassType& item) { if (top > 0) { item = items[--top]; return true; } else return false; } template<class ClassType> Stack<ClassType>& Stack<ClassType>::operator=(const Stack<ClassType>& st) { if (this == &st) return *this; delete[] items; stackSize = st.stackSize; top = st.top; items = new ClassType[stackSize]; for (int i = 0; i < top; ++i) { items[i] = st.items[i]; } return *this; } template<class ClassType> Stack<ClassType>::Stack(const Stack& st) { stackSize = st.stackSize; top = st.top; items = new ClassType[stackSize]; for (int i = 0; i < top; ++i) { items[i] = st.items[i]; } } namespace stack { template<class T> class beta { private: template<typename V> class hold; hold<T> q; hold<int> n; public: beta(T t, int i) :q(t), n(i) {}; template<typename U> U blab(U u, T t); void Show() const { q.show(); n.show(); } }; template<class T> template<typename V> class beta<T>::hold { private: V val; public: hold(V v = 0) :val(v) {} void show()const { std::cout << val << std::endl; } V Value() const { return val; } }; template<class T> template<typename U> U beta<T>::blab(U u, T t) { return (n.Value() + q.Value()) * u / t; } } template<template<typename T> class Thing>//未知类型模板定义 class Crab { private: Thing<int> s1;//未知类型的模板类 Thing<double> s2;//未知类型的模板类 public: Crab() {}; bool Push(int a, double x) { return s1.Push(a) && s2.Push(x); } bool Pop(int& a, double& x) { return s1.Pop(a) && s2.Pop(x); } }; int main() { Crab<Stack> nebula; int ni; double nb; while (std::cin >> ni >> nb && ni > 0 && nb > 0) { if (!nebula.Push(ni, nb)) break; } while (nebula.Pop(ni, nb)) { std::cout << ni << " " << nb << std::endl; } }
-
模板类声明可以有友元,模板类的友元分以下三类:
- 非模板友元。
- 约束模板友元,即友元类型取决于类被实体化时的类型。
- 非约束模板友元,即友元的所有具体化都是类的每个具体化的友元。
- 注:模板为不同类型的对象使用的类是不同的,如int的对象使用的int具体化的类,double的对象使用的是double具体化的类。在约束模板友元函数中在类前面声明一个模板函数的原因,友元函数是一个模板函数的实例化,且实例化的类型与类模板类型相关.
#include<iostream> template<class T> class HasFriend { private: T item; static int ct; public: HasFriend(const T& i) :item(i) { ++ct; } ~HasFriend() { --ct; } friend void counts(); friend void reports(HasFriend<T>&); }; template<class T> int HasFriend<T>::ct = 0; //non-template friend to all HasFriend<T> classes void counts() { std::cout << "int counts: " << HasFriend<int>::ct << "; "; std::cout << "double count: " << HasFriend<double>::ct << std::endl; } //non-template friend to the HasFriend<int> class void reports(HasFriend<int>& hf) { std::cout << "HasFriend<int>: " << hf.item << std::endl; } //non-template friend to the HasFriend<double> class void reports(HasFriend<double>& hf) { std::cout << "HasFriend<double>: " << hf.item << std::endl; } int main() { std::cout << "No objects declared; "; counts(); HasFriend<int> hfil1(10); std::cout << "After hfil1 declared; "; counts(); HasFriend<int> hfil2(20); std::cout << "After hfil2 declared; "; counts(); HasFriend<double> hfdb(10.5); std::cout << "After hfdb declared; "; counts(); reports(hfil1); reports(hfil2); reports(hfdb); return 0; }
No objects declared; int counts: 0; double count: 0 After hfil1 declared; int counts: 1; double count: 0 After hfil2 declared; int counts: 2; double count: 0 After hfdb declared; int counts: 2; double count: 1 HasFriend<int>: 10 HasFriend<int>: 20 HasFriend<double>: 10.5
#include<iostream> template<typename T> class ManyFriend { private: T item; public: ManyFriend(const T& i) :item(i) {}; template<typename C, typename D> friend void show2(C&, D&); }; template <typename C, typename D> void show2(C& c, D& d) { std::cout << c.item << ", " << d.item << std::endl; } int main() { ManyFriend<int> hfi1(10); ManyFriend<int> hfi2 = 20; ManyFriend<double> hfdb{ 10.5 }; std::cout << "hfi1, hfi2: "; show2(hfi1, hfi2); std::cout << "hfdb, hfi2: "; show2(hfdb, hfi2); return 0; }
hfi1, hfi2: 10, 20 hfdb, hfi2: 10.5, 20
#include<iostream> template<typename T> void counts(); template<typename T> void report(T&); template<class TT> class HasFriendT { private: TT item; static int ct; public: HasFriendT(const TT& i) :item(i) { ++ct; }; ~HasFriendT() { --ct; }; friend void counts<TT>(); friend void report<>(HasFriendT<TT> &); }; template<typename T> int HasFriendT<T>::ct = 0; template<typename T> void counts() { std::cout << "template size: " << sizeof(HasFriendT<T>) << "; "; std::cout << "template counts(): " << HasFriendT<T>::ct << std::endl; } template<typename T> void report(T& hf) { std::cout << hf.item << std::endl; } int main() { counts<int>(); HasFriendT<int> hfi1(10); HasFriendT<int> hfi2(20); HasFriendT<double> hfdb(10.5); report(hfi1); report(hfi2); report(hfdb); std::cout << "counts<int>() output:\n"; counts<int>(); std::cout << "count<int>() output:\n"; counts<double>(); return 0; }
hfi1, hfi2: 10, 20 hfdb, hfi2: 10.5, 20
-
CPP可以为模板起别名,但是用的数using,当然using语法可以用于非模板,这是与typedef等价:
template<typename T> using arrtype=std::array<T,12>; //重命名后可以进行一下创建 arrtype<double> gallons; arrtype<int> days; arrtype<std::string> months; typedef const char *pc1; //上面语法相当于下面的语法 using pc1=const char*; typedef const int *(*pa1)[10]; //上面语法相当于下面的语法 using pa1=const int *(* )[10];
cpp primer plus笔记010-继承
最新推荐文章于 2024-08-23 17:37:15 发布