#include
using namespace std;
/*知识点:
0.定义类时,类的构造函数一般必须是public的,除非特殊用途的类
public或private protected 说明起作用的范围是从申明处开始
下面的所有范围,直到遇到另一个属性申明。
类中的成员函数主体可以直接写在类中,也可以先申明函数原型,
然后在在类外定义函数体,同时需要加上在函数原型前加 "类名::"
class A
{
public:
A(){}
int i; //此处i是public
void Test(); //此处Test()是public
private:
int j;
void Test2(){}; //函数在类内部定义,此处Test2()是private
};
void A::Test()// 函数在类外定义
1.对象无法直接访问该对象种的私有成员变量,如果要访问,可以用类中的公有成员函数来访问。
class A
{
private:
int i;
};
int main()
{
A b;
int c=b.i;//错误
}
2.类申明中如果省略了构造函数,系统提供默认的不带参数的构造函数,
如果自己定义了构造函数,则系统不提供不带参数的构造函数。
class A
{
private:
int i;
};
int main()
{
A b;//调用系统默认构造函数
}
class A
{
public:
A(int c){ cout<<"c="<private:
int i;
};
int main()
{
A b;//错误,此时系统不提供默认构造函数
A c(3)//调用定义的构造函数
}
3.类的构造函数可以有多个,但是参数必须不相同(参数个数不同或者参数类型不同)
生成该类的对象时,必须按照类中存在的构造函数的参数形式进行调用。
4. 如果实际调用时参数个数小于构造函数,则无法完成对象构造,除非构造函数参数给出了默认值
class A
{
public:
A(int c,int d=0)//该构造函数的参数d有默认值
{
cout<<"c="< cout<<"d="< }
private:
int i;
};
int main()
{
A c(3);//可以通过,此时d默认为0
A d(3,4);
}
5.继承时继承类包含所有的基类中的数据成员和成员函数,
但是继承类成员函数不能直接访问基类的私有变量,
可以直接访问基类中的保护成员变量和共有成员变量,
若要访问基类中的私有变量,则可以通过基类的公有函数。
class A
{
public:
A( int i,int j,int k)
{
a=i;
b=j;
c=k;
}
private:
int a;
protected:
int b;
public:
int c;
};
class B:public A
{
public:
B(int i,int j,int k):A(i,j,k)
{
6.构造函数调用顺序就是系统在编译时对象初始化的顺序
是从最低层的基类,继承类的成员变量对象,再到继承类。
析构函数的调用完全和构造函数的对象调用相反。
class A
{
public:
A()
{
cout<<"A is creating"< }
~A()
{
cout<<"A is deleting"< }
};
class B
{
public:
B()
{
cout<<"B is creating"< }
~B()
{
cout<<"B is deleting"< }
};
class AA:public A
{
public:
AA()
{
cout<<"AA is creating"< }
~AA()
{
cout<<"AA is deleting"< }
};
class BB:public B
{
public:
BB()
{
cout<<"BB is creating"< }
~BB()
{
cout<<"BB is deleting"< }
};
class Test:public AA
{
public:
Test()
{
cout<<"Test is creating"< }
~Test()
{
cout<<"Test is deleting"< }
private:
BB x;
};
int main()
{
Test c;
}
7. C++编译器强制规定了,继承类的基类没有初始化,或者成员对象变量未初始化
就不能进入入继承类构造函数主体。
继承类初始化列表首先要确保调用基类的构造函数(默认调用无参基类构造函数)
如果继承类中还有成员对象变量,则也必须先初始化(默认调用该类的无参构造函数)
如果不想用默认的构造函数构造,可以在初始化列表中用带参数的构造函数初始化。
class A
{
public :
A(int i)
{
cout<<"i="< }
};
class B:public A
{
public:
B() //错误,无法找到基类的构造函数
//可以改成B():A(0)
//此处如果不用列表初始化,系统应该调用A()
//但是A类已经申请了带参数的构造函数,系统将不再提供A();
{
}
}
int main()
{
B c;
}
8. C++中函数参数可以是普通的变量,变量的引用,变量的指针,
其中,参数是普通变量时,编译器采用复制该变量供函数使用,
参数是变量的引用时,编译器将该变量直接提供给函数使用,
参数是变量的指针时,编译器将该变量的地址复制给函数使用。
如果要改变原来的变量,则必须用引用参数或者指针参数。
9.友元函数,或者友元类生成的对象可以直接访问该类中的私有变量
class A
{
private:
int a;
friend class B;//友元类
friend void get(A& t);//友元函数
};
void get(A& t)
{
cout<<"a="<}
class B
{
public:
void Test(A& t)
{
cout<<"a="< }
};
int main()
{
A b;
get(b);
B c;
c.Test(b);
}
10. const是常量,C++中的常量一般必须出初始化,
类中的常量必须在构造函数之前进行初始化
static 是静态变量,它在程序退出以前一直存在。
类中的静态变量的用处是为了使由该类生成的对象
都共用同一个变量,这样所有的对象都可以对其进行修改
类中的静态变量必须在类外进行初始化。
int main()
{
A c;
c.print();
}
11.为了实现多态性,C++中引入了虚函数,虚函数只在基类进行申明,
申明方法是在函数前加上virtual,继承自基类的函数则省略关键字。
多态的特点是,如果用基类的指针指向继承类对象,实际调用函数时,
系统会自动判断段该指针指向的类型,从而调用相应的继承类的函数。
除非继承类没有该函数
而如果函数没有被申明为virtual,那么基类的指针只会调用基类的函数,
注意:系统仍然会对继承类函数中调用的函数进行多态判断
也就是说,继承类函数中的函数调用是直接调用本类的函数
class A
{
public:
virtual void f1(){cout<<"A::f1()"< virtual void f2(){cout<<"A::f2()"< void f3(){cout<<"A::f3()"< void f4(){f3();f1();}
};
class B:public A
{
public:
void f1(){cout<<"B::f1()"< void f3(){cout<<"B::f3()"< void f4(){f3();f1();}
};
int main()
{
A *c;
B d;
c=&d;
c->f1();cout<<"体现了virtual多态性"< c->f2();cout<<"体现了(如果继续承类没有相应的函数则调用基类中的函数)"< c->f3();cout<<"体现了没有多态性的情况"< c->f4();cout<<"体现函数中调用函数时的现象(基类指针调用)"< d.f4(); cout<<"体现函数中调用函数时的现象(继承类调用)"<}
12:
结构体和类的定义方法和使用方法基本相同,唯一不同的是
类的成员变量如果采用默认时(不写public 或者private)是private的。
而结构体的成员变量如果采用默认时是public的。
另外在用
typedef struct B B;//这句在C++中可以省略
class A
{
int a;//默认是private
public :
A(int x){a=x;cout<<"这是一个类";}
void print(){cout<
};
struct B
{
B d(2);
d.print();
}
13. 应当引起注意的地方。
类名直接引用的情况:
(1)静态成员变量 类名::变量名
(2)静态成员函数 类名::函数名
(3)成员函数中引用成员变量或成员函数 类名::变量名,类名::函数名
除了这3种情况,必须用对象进行引用。
对象引用私有成员变量只能出现在友元函数或成员函数中
所有的函数申明都必须有返回类型
多于void返回类型的函数,定义中可以不加return 语句。
而对于其他返回类型必须要有return 语句
申明对象的方法:
类名 对象变量(参数);
类名 对象变量=类名(参数);
类名 *对象指针变量名=new 类名(参数);
申明对象数组的方法
类名 *对象数组指针变量名=new 类名[数组长度];
类名 对象数组变量名[数组长度];
printf()函数的语法。
定义常量的方法
枚举变量的定义方法
for循环的书写方法
引用数组中元素的两种方法
定义:
类型* 变量=new 类型[长度];
引用:变量[元素下标] *(变量+元素下标)
函数申明中参数一定要加类型说明
而函数定义内部或者函数调用时引用该参数的地方则不需要类型说明了。
同样对于类的构造函数中的申明部分是一定要加类型说明
而对于该构造函数的初始化列表部分和定义部分则不需要类型说明。
继承对象调用基类的成员函数的方法
对象名.基类名::函数名(参数);
virtual 继承是为了消除二义性
对象指针的删除方法和对象数组的删除方法
delete 和delete[]
14. 类中的静态成员函数可以以 类名::函数名(参数)来调用。
因为静态成员函数是在编译时连接的,也就是说,在还没有
对象生成时应当可以调用的,因此静态成员函数定义中
不能引用类中的非静态成员变量或函数。
class A
{
int x;
int y;
public:
A()
{
cout<<"生成A对象"< }
static void test()
{
cout<<"这是个静态成员函数"< cout< }
};
int main()
{
A::test();
}
15. const放在函数名前,函数参数中,以及函数申明后分别表示含义
const放在函数名前,表示返回的变量为常量
const放在函数参数中,表示程序不可以改变参数对应的变量。
const放在函数后,表示函数定义内不可以改变类中的成员变量。
class A
{
int a;
public:
A(int i)
{
a=i;
cout<<"生成A对象"<
}
const A test1(int x)
{
a=x;
return *this;
}
int test2(const A x)
{
// x.a=3;//错误,此处参数为const的,不能对其进行改变
return x.a;
}
int test3(int x) const
{
// a=x; //错误,此处const表示函数定义内部可以改变类的成员变量
return a;
}
};
int main()
{
A c(1);
//cout< //常量不可以进行改变,所以后面的.test2(1)对其进行改变是错误的
//如果把test1前的const去掉后则可以改变
}
16
类构造函数中初始化列表应用
(1)
基类中有成员变量继承类继承基类后需要对对应的基类中的成员变量进行初始化,
这时候需要调用基类的构造函数进行初始化(默认调用无参数的构造函数)
初始化必须在初始化列表中进行 基类名1(参数1),基类名2(参数2).....
(2)
继承类有对象类型的成员变量,在继承类完成自己的构造函数以前必须对该变量初始化
这时候需要调用成员变量对应的构造函数
初始化必须在初始化列表中进行 成员变量名1(参数1),成员变量名2(参数2)....
(3)
继承类自己的成员变量进行初始化时也可以在参数化列表中进行
调用方法是 变量名1(参数1),变量名2(参数2).....
对于比较复杂的继承类,有时候应用了上面所有的三种情况
比如下面的。
*/
class BASE1
{
int first;
public:
BASE1(int x)
{
first=x;
cout<<"BASE1 构造完成"<}
int getfirst()
{
return first;
}
};
class BASE2
{
int second;
public:
BASE2(int y)
{
second=y;
cout<<"BASE2 构造完成"<}
int getsecond()
{
return second;
}
};
class OTHER1
{
char first;
public:
OTHER1(char c)
{
first=c;
cout<<"OTHER1 构造完成"<}
int getfirst()
{
return first;
}
};
class OTHER2
{
char second;
public:
OTHER2(char d)
{
second=d;
cout<<"OTHER2 构造完成"<}
int getsecond()
{
return second;
}
};
class Test:public BASE1,public BASE2
{
char m,n;
OTHER1 s;
OTHER2 x;
public:
Test(int a,int b,char x,char y,char c,char d):BASE1(a),BASE2(b),s(x),x(y),m(c),n(d)
{
cout<<"Test 构造完成"<}
void print()
{
cout<<"BASE1中成员变量first="< cout<<"BASE2中成员变量second="< cout<<"OHERT1对象中first="<<(char)s.getfirst()< cout<<"OHERT2对象中second="<<(char)x.getsecond()< cout<<"Test对象中的m,n="<}
};
int main()
{
Test s(1,2,'c','d','p','q');
s.print();
}
阅读(2708) | 评论(0) | 转发(1) |