C++面向对象

来源:互联网 发布:域名是知识产权吗 编辑:程序博客网 时间:2024/06/10 16:59
1.公有部分可以直接这样初始化
class Time{
public:
int h;
int m;
int s;
};
Time t1 {1,2,3};


2.构造函数用于为对象分配空间和进行初始化,属于某一个类。在系统建立对象时自动调用执行。
(1)构造函数的名字与它的类名必须相同
(2)没有类型,没有返回值
(3)可在类外定义
(4)可带参数
例:
class Time
{
public:
Time(int, int, int);
int h;
int m;
int s;
};
Time::Time(int a, int b, int c)
{
h = a;
m = b;
s = c;
}
int main ()
{
Time t1(1,2,3);
cout<<t1.h<<t1.m<<t1.s<<endl;
}


(5)形参初始化表
class Time
{
public:
Time(int a, int b, int c): h(a), m(b), s(c){}
int h;
int m;
int s;
};

(6)一个类可以有多个同名构造函数,函数的参数个数、参数类型各不相同
class Time
{
public:
Time();
Time(int, int, int);
int h;
int m;
int s;
};

(7)默认参数值的构造函数
class Time
{
public:
Time(int a = 2, int b = 1, int c = 1);
int h;
int m;
int s;
};
注意:不要使用重载构造函数和默认参数值的构造函数

(8)构造函数在对象数组中的用法
class Time
{
public:
Time(int, int, int);
int h;
int m;
int s;
};
Time ti[3] = {Time(1,2,3), Time(4, 5, 6), Time(7, 8, 9)};

(9)复制构造函数
两种对象的复制方法:
①类名 对象2(对象1)
②类名 对象2 = 对象1
下面三种情况会自动调用复制构造函数
当用赋值对象创造对象时(方法①)
将实参对象传递给形参对象时
函数的返回值是类的对象时

3.析构函数与构造函数相反,当对象的声明周期结束时会自动调用析构函数,释放对象占用的内存空间
(1)static局部对象和全局对象要到main函数结束或者exit命令时才自动执行析构函数释放对象
(2)用new建立动态对象,用delete时,自动执行析构函数释放对象
(3)析构函数名以~符号开始,后面跟类名
(4)析构函数没有数据类型,返回值和形参,一个类只能有一个析构函数
(5)先调用构造函数的对象最后调用析构函数,相当于一个栈,先进后出

4.指向对象的成员函数的指针
class Time
{
public:
void display();
private:
int h;
int m;
int s;
};
void Time::display()
{
cout<<h<<m<<s<<endl;
}
int main ()
{
Time t1;
void (Time::*pFunc)();
pFunc = &Time::display;
(t1.*pFunc)();
}

5.this指针:在对象调用成员函数时,把对象的地址赋予this指针
void Time::display()
{
cout<<h<<m<<s<<endl;
}
等价于
void Time::display()
{
cout<<this->h<<this->m<<this->s<<endl;
}

6.常对象中要修改某个成员为“可变数据成员”:
mutable 类型 数据成员;

7.const成员函数:类型 函数名 (形参表) const
(1)const成员函数只能调用const数据成员
(2)一个const对象只能调用它的const成员函数
(3)const成员函数可以引用任何数据成员,但不能改变值
(4)非const成员函数不能引用const对象的数据成员

8.静态数据成员static
(1)当一个对象的静态成员的值被改变了,所有该类的对象的该值也会跟着改变
(2)不能用构造函数对静态数据成员进行初始化
(3)既可以用对象名引用静态成员,也可以用类名引用
(4)静态成员在对象外单独开辟内存空间
(5)如果程序未对静态数据成员初始化,则编译系统将它自动赋值为0
class Time
{
public:
static int h;
private:
static int m;
static int s;
};
int Time::h = 0;


9.静态成员函数static
(1)静态成员函数属于类而不属于对象
(2)静态成员函数只能访问静态数据成员(应该只能访问公有的static数据成员 待进一步验证)
(3)不能这样调用: Time::display(); (待进一步验证)

10.友元friend
(1)定义友元函数时,形参通常是类引用:friend void display(Time&);
(2)将普通函数声明为友元函数。
class Time
{
public:
Time(int a, int b, int c):h(a), m(b), s(c){};
friend void display(Time&);
private:
int h, m, s;
};
void display(Time &t1)
{
cout<<t1.h<<t1.m<<t1.s<<endl;
return;
}
int main ()
{
Time t1(2, 3, 4);
display(t1);
return 0;
}
(3)友元成员函数:成员函数声明为friend后就可以被其他类调用了
class Date;
class Time
{
public:
Time(int a, int b, int c):h(a), m(b), s(c){};
void display(Date&);
private:
int h, m, s;
};
class Date
{
public:
friend void Time::display(Date&);
Date(int a, int b, int c):y(a), m(b), d(c){};
private:
int y, m, d;
};
void Time::display(Date &t1)
{
cout<<t1.y<<t1.m<<t1.d<<endl;
cout<<h<<m<<s<<endl;
return;
}
int main ()
{
Time t1(2, 3, 4);
Date d1(5, 6, 7);
t1.display(d1);
return 0;
}


11.类模板 用于适配不同类型的数据
template<class numtype>
class Compare
{
public:
Compare(numtype a, numtype b)
{
x = a;
y = b;
}
numtype max(void)
{
return (x > y ? x : y);
}
numtype min(void)
{
return (x > y ? y : x);
}
private:
numtype x, y;
};
int main ()
{
Compare<int> compare_int(2, 6);
Compare<float> compare_float(2.3, 2.32);
cout<<"maxint="<<compare_int.max()<<endl<<"maxfloat="<<compare_float.max()<<endl;
return 0;
}


12.重载运算符
class Complex
{
public:
Complex(int a, int b):x(a),y(b){}
Complex operator + (Complex &t);
void display()
{
cout<<"x="<<x<<endl<<"y="<<y<<endl;
}
private:
int x, y;
};
Complex Complex::operator + (Complex &t)
{
Complex c(0, 0);
c.x = t.x + x;
c.y = t.y + y;
return c;
}
int main ()
{
Complex str[3] = {Complex(2,3), Complex(4,5), Complex(0, 0)};
str[2] = str[0] + str[1];
str[2].display();
return 0;
}
相当于 str[0].operator +(str[1])

(1)不能从在的运算符只有5个(.)(.*)(::)(sizeof)(? :)
(2)重载不改变操作数的个数
(3)重载不改变运算符的优先级
(4)运算符重载函数不能带默认值参数
(6)运算符重载函数必须与自定义类型的对象联合使用,其参数至少有一个是类对象或类对象引用
(7)C++默认提供=和&运算符重载
(8)运算符重载函数可以是类成员函数也可以是类友元函数,还可以是普通函数
运算符重载类友元函数:
class Complex
{
public:
Complex(int a, int b):x(a),y(b){}
friend Complex operator + (Complex &t1, Complex &t2);
void display()
{
cout<<"x="<<x<<endl<<"y="<<y<<endl;
}
private:
int x, y;
};
Complex operator + (Complex &t1, Complex &t2)
{
Complex c(0, 0);
c.x = t1.x + t2.x;
c.y = t1.y + t2.y;
return c;
}
int main ()
{
Complex str[3] = {Complex(2,3), Complex(4,5), Complex(0, 0)};
str[2] = str[0] + str[1];
str[2].display();
return 0;
}
相当于:
operator +(str[0], str[1])

13.派生类




多继承:派生类从多个基类中集成,如:
class A : private B, public C{};


派生类的构造函数给基类集成过来的成员赋值:
class father{
public:
int a, b, c;
father(int i, int j)
{
a = i;
b = j;
}
private:
int d, e, f;
};
class son:public father{
public:
int m, n;
son (int f1, int f2, int s1, int s2):father(f1, f2)
{
m = s1;
n = s2;
}
};
int main ()
{
son son1(1, 2, 3, 4);
cout<<son1.a<<son1.b<<son1.m<<son1.n<<endl;
}


(1)当建立一个派生类对象时,先调用基类构造函数,再执行派生类构造函数。
(2)当释放派生类对象时,先调用派生类的析构函数,在调用基类的析构函数。
(3)当多层派生时,只需要用这个方法来给直接派生的基类成员赋值

14.子对象:对象里面的对象
有子对象的派生类构造函数的一般格式为:
派生类名(总参数表):基类名(基类参数表),子对象名(子对象参数表)
{
派生类新增成员的初始化语句;
}
例:
class father{
public:
father(U32 u32Param1, U32 u32Param2)
{
u32Age = u32Param1;
u32Job = u32Param2;
}
void display();
protected:
U32 u32Age;
U32 u32Job;
};
void father::display()
{
cout<<"u32Age="<<u32Age<<endl<<"u32Job="<<u32Job<<endl;
}


class son:private father{
public:
father father1; //子对象
son(U32 u32Age1, U32 u32Job1, U32 u32Age2, U32 u32Job2, U8 u32Sex1):father(u32Age1, u32Job1), father1(u32Age2, u32Job2)
{
u32Sex = u32Sex1;
}
void display();
private:
U32 u32Sex;
};
void son::display()
{
cout<<"u32Age="<<u32Age<<endl<<"u32Job="<<u32Job<<endl<<"u32Sex="<<u32Sex<<endl;
}


int main()
{
son son1(18, 14, 19, 15, 50);
cout<<"son's param:"<<endl;
son1.display();
cout<<"father1's param:"<<endl;
son1.father1.display();
}
注意:如果在基类或者子对象的类声明了带参数的构造函数,就必须定义派生类的构造函数,并传递参数表

15.多重继承
1.声明多重继承的构造函数:
class D : public A, private B, protected C{
public:
D(a, b, c):A(a), B(b), C(c){
新增参数初始化语句;
}
}

2.若派生类和基类有同名的参数时,默认情况下,派生类对象使用的是派生类的成员。若要使用基类的成员,则需要在前面加标识符
例:
若上述的ABCD都有相同成员n,则D类的对象要访问基类A的成员n,需这样:
D d(...);
d.A::n = 2;

3.虚基类
若上述的ABC都是由同一个基类E派生出来的,而类D只需要继承其中的一份E,则ABC在继承时需要成名为虚继承:
class 派生类名:virtual 继承方式 基类名
E就被称为虚基类
注意:D的构造函数必须对虚基类E进行初始化,而不应该由ABC对E进行初始化。
例:
class Furniture {
public:
Furniture(U32 u32L, U32 u32H)
{
u32Length = u32L;
u32Hight = u32H;
}
void display()
{
cout<<"u32Length = "<<u32Length<<endl<<"u32Hight = "<<u32Hight<<endl;
}
private:
U32 u32Length;
U32 u32Hight;
};


class Bed:virtual public Furniture{
public:
Bed(U32 u32L, U32 u32H):Furniture(u32L, u32H){}
void sleep_cout()
{
cout<<"used to sleepping."<<endl;
}
};


class sofa:virtual public Furniture{
public:
sofa(U32 u32L, U32 u32H):Furniture(u32L, u32H){}
void watchTV_cout()
{
cout<<"used to watching TV."<<endl;
}
};


class sofabed:public Bed, public sofa{
public:
void function()
{
cout<<"used to sleepping and watching TV."<<endl;
}
sofabed(U32 u32L, U32 u32H):Furniture(u32L, u32H), Bed(0, 0), sofa(9, 9){}
};
int main()
{
sofabed sofabed1(2, 3);
sofabed1.display();
sofabed1.sleep_cout();
sofabed1.watchTV_cout();
sofabed1.function();
}
注意:虚基类的继承,派生类会比普通继承长度多4字节,因为会多一个虚指针

16:虚函数
虚函数的工作原理是:在派生类中定义与基类函数同名的函数,通过基类指针或者引用来访问基类或者派生类中的同名函数


https://wenku.baidu.com/view/15b1931deff9aef8941e06a4.html?from=search

643

原创粉丝点击