#ifndef __xxx__//防卫式声明,公共头文件内容
#include <iostream>
using namespace std;
#define __xxx__
#endif
//避免变量名冲突可以使用命名空间
//函数外只能定义全局变量或者对象,而不能执行语句及调用函数
//除了常见的继承之外的其他两种面向对象关系,委托和复合[最后三节,用到再学]
class CStu
{
//默认,类内可见而protected:本类和子类可见
private:
//对象的大小根据属性计算,函数被放在代码区,计算大小时不被计入
int age;
int name;
int& t1;
const int t2;
int h[10];
int* p;
public:
//静态成员变量,只有静态整型常量才能类内初始化,所有对象共有(包括子类),生命周期从编译直至程序结束
static int stat;
//只要用户声明构造函数则无默认的构造函数
//在构造函数之前通过初始化列表初始化,比大括号内赋值效率高
//引用、const必须用初始化列表初始化,数组看编译器情况使用初始化列表和结构体可使用初始化列表
//默认[non - explicit] 加上explicit进行隐式类型转换
CStu(int a = 0, int b = 0, ...)
:age(a), name(b), t1(a), t2(b){//初始化同声明顺序,若所有变量全被初始化则不能使用CStu()
this->name = name;//类的指针类型,系统默认传递给函数(非静态)的隐含参数
}
//只要用户声明析构函数则无默认的析构函数
//无参数,没有重载,生命周期结束时自动调用
~CStu() {
//xxx;
}
//函数在类内定义,自动成为 inline 候选;而在类外定义,可声明为 inline
//若代码少,流程直接,调用频繁可用inline,它用相应的代码替换调用,以空间换时间
//普通函数(非成员函数)加上inline关键字后必须函数体和声明结合在一起,否则编译器将它作为普通函数来对待
inline void Test() {
//xxx;
}
//构造和析构不能是常函数,常对象只能调用常函数
//this指针类型是 const CStu*
//常函数,不需修改数据内容一定要加const(变量同理)
void fun() const {
//xxx;
}
//若const和非const同时存在,常对象调用常函数,非常对象调用非常函数
void fun() {
//xxx;
}
void Test1(int a);//类内定义内外声明
friend void fun1(); //友元函数,不受访问修饰符影响,不能被继承传递,friend关键字只出现在声明处
friend class CTeach;//友元类,不受访问修饰符影响,不能被继承传递,friend关键字只出现在声明处
friend ostream& operator<<(ostream& os, const CStu& st);
//传引用能避免形参或返回时创建临时对象,返回在函数内创建的变量不能传引用
//默认拷贝构造函数,逐个复制非静态成员的值(浅拷贝)
//指针成员不能直接赋值,要用内存拷贝,否则指针指向相同,析构时冲突(深拷贝)
//拷贝构造,参数是本类的常引用
//若用户定义拷贝构造函数,c++不会再提供任何默认构造函数
CStu(const CStu& a) :t1(a.t1), t2(a.t2) {
//xxx;
this->p = new int;
this->p = a.p;
}
CStu& operator=(const CStu& a) {//运算符重载,拷贝赋值
if (this == &a)//检测自我赋值保证安全+提高效率
return *this;
//xxx;清空左边空间把右边内容复制倒左边
}
static int sta() {//静态函数,无this,只能调用静态成员,所有对象共有,不能是虚函数
return stat;//xxx;
}
//类外算术,关系,位运算(左参,右参)
//建议类内、,*,++和--后置还需int n标记=,[ ],(),->,+=,<<=(默认类的类型,单参)
//重载类型转换:没有返回类型,没有参数,有返回值,成员const函数
//有时多种类型转化同时存在会导致程序无法选择确定的转换函数
//除了赋值号(=)外,基类中被重载的操作符都将被派生类继承
void operator+(CStu& st) {//运算符重载返回值需考虑全面如c3+=c2+=c1
//xxx;
}
//inline和构造不能是虚函数,析构可以是虚函数
//普通析构本身只会调用所属指针类型的,虚析构可以调用子类的
//根据父指针找到父函数,若是虚函数执行子类重写(未重写则执行本身),若不是则执行本身
//对象若有虚指针,其空间的最开始四字节内容是虚表的地址也叫虚指针,虚表内存储的是虚函数的地址
//若虚函数显式继承重写,使用子类虚函数的地址,若没有则使用父类的地址
virtual void vary(){
//xxx;
}
//纯虚函数不能实例化对象,必须子类实现,有则是抽象类,全是则是接口类
// virtual void xu() = 0;子类必须定义
};
//<< >>只能为类外/友元,cin还需检查输入是否出错
ostream& operator<<(ostream& os, const CStu& st){
os << st.age;//cout是ostream对象,cin同理a
return os;
}
void operator-(CStu& st) {//此处是一元 ↑是二元
//xxx;
}
int CStu::stat = 1;//类外初始化静态成员变量
void CStu::Test1(int a) {//函数定义时不允许写默认值 如a=2
//xxx;
}
class CTeach {//友元类
public:
CStu stu2;
void fun2(){
stu2.Test();
}
};
//private(默认)-子类private、protected-父公降其他不变、public-不变
class CWork :public CStu {//继承类 若是虚继承(加上virtual)不会导致多继承中访问不明确
public://大多数情况下要把构造放在public下
CWork() :CStu(1, 2) {//↓调用构造↑调用析构,父类有参需要通过子类初始化列表传递参数
//xxx;
}
//父子名字同,子覆盖父,覆盖≠重载,可以用类名作用域区分
//父类有virtual是多态叫重写和子类除内容完全相同 没有是覆盖
void vary() {///默认virtual
//xxx;
}
};
int main()
{
//静态联编在编译阶段就将函数实现和函数调用关联,对象调用而不是指针调用
//动态联编在程序执行的时候才将函数实现和函数调用关联,指针调用+虚函数+可向上转型
CStu op(1, 2);//声明对象,同类的对象互为友元
CStu cs = op;//调用拷贝构造,若是CStu cs,cs=op两步则涉及运算符重载,拷贝赋值
op.Test();//成员调用
CStu* op1 = new CStu(3, 4);//声明指针对象,遇到new调用构造,遇到delete调用析构
op1->Test(); //成员调用
delete op1;//调用析构
CStu(5, 6);//临时对象,作用域只在此行
const CStu c1(2, 1);//常对象
c1.fun();
cout << c1.stat << " " << CStu::sta();//通过类对象和类作用域调用
CWork* cw = new CWork();//声明子类对象
cw->Test1(1);//调用父类函数
delete cw;
//多态,父类指针指向子类空间,一般只能使用CStu的成员
CStu* p = new CWork();//↑如果在此基础上增加virtual可调用被指向的子类
return 0;
}
#include <iostream>
using namespace std;
struct Node {
int a;
double b;
};
//模板可以有多个参数,但只对直接下方起作用
//泛化
template<typename T, class N> class TestClass {
public:
bool comp(T num1, N num2) {
//xxx;
}
};
//特化
template<>class TestClass<int, double>{
bool comp(int num1, double num2) {
//xxx;
}
};
//偏特化
template<class N> class TestClass<int, N> {
public:
bool comp(int num1, N num2) {
//xxx;
}
};
//实例化
template class TestClass<int,double>;
//泛化 原始->特化->泛化
template<typename T,typename K> void fun(T a,K b) {
cout << a;
}
//特化
template<> void fun<Node,Node>(Node no1, Node no2) {
//cout << no.a;
}
/*在函数模板中不存在偏特化,由于函数模板偏特化和函数重载决策的矛盾
template<typename N> void fun<int, N> fun(int i, N num2) {
//xxx;
}*/
//实例化,屏蔽不想输入的类型
template void fun<int,double>(int i,double j);
template <typename H> class people {
public:
int a;
};
//使用类模板,只有类模板可以有默认值,指定←
template<typename T, typename J> class CStu {
public:
T a;
CStu(people<char>& a) {
//xxx;
}
CStu() {
//xxx;
}
void show();
virtual void test() {
//xxx;
}
};
template<typename T, typename J>
void CStu<T, J>::show() {//类外实现的函数模板
//xxx;
}
template<typename K, typename S, typename F>//父子个数可不同
class CTeach :public CStu<S, F> {
public:
CTeach() {
//xxx;
}
void test() {
//xxx;
}
};
//成员模板
class Base1 { };
class Derived1 : public Base1 { };
class Base2 { };
class Derived2 : public Base2 { };
template <class T1, class T2>struct pair {
T1 first;
T2 second;
template<class U1, class U2>pair(const pair<U1, U2>& p) :
first(p.first), second(p.second) {
//xxx;
}
};
int main()
{
//多态,必须左右对应,子类没有模板可不写
CStu<int, double>* c = new CTeach<char, int, double>;
c->test();
CStu<int, double> cs();
//模板参数列表,可将默认值覆盖,但也可不传,但必有<>
CTeach<char, int, double> ct();
people<char> po;
CStu<int, people<char>>pr(po);//类型是类的模板
return 0;
}