面向对象
1、基本特征
1.抽象
2.封装
3.继承
子类可以自动共享父类的数据结构和方法的机制,
单继承:子类只继承以父类的数据结构和方法。
多继承:子类可以继承多个父类的数据结构和方法(需小心二义性)。
4.多态
不同类对象调用相同的方法可以产生不同的结果
2、声明一个类
class class_name{
permission_lable:
member1;
permission_lable:
member2;
…….
};
permission_lable:权限标识符,可以是public、private、protected三个中的一个。
private(默认为该类型):私有成员,只有同一个类的其它成员或该类的“friend”类可以访问这些成员。
protected:保护成员,只有同一个类的其他成员或“friend”类或该类的子类可以访问这些成员
public:公有成员,任何可以看到该类的地方都可以访问这些成员。
3、类声明内外实现成员函数的区别
在类中直接编写的成员函数会被编译成内联函数,而在外部编写的函数会被编译成普通函数。
内联函数优点:加快运行效率
缺点:造成程序体积庞大。
4.const成员函数
加了该修饰后,函数体内的代码不能有任何修改类数据成员的代码。
int get_value() const{
//value++;//编译会报错
return value;
};
5、构造函数
特点:
1.命名必须和类名完全相同
2.功能主要用于在类的对象创建时定义初始化成员的状态。
3.没有返回值,也不能用void来修饰。
4.构造函数不能被直接调用,必须通过new运算符在创建对象或直接定义对象时才会被自动调用。
5.构造函数可以省略
6.如果把构造函数定义为私有,责无法创建对象。
7.有回滚效果
8.不能为虚函数
class stu{
private:
int age;
string name;
public:
stu(int a, string n);
int getAge(){ return age; }
string getName(){ return name; }
};
stu::stu(int a, string n)
{
age = a;
name = n;
}
int _tmain(int argc, _TCHAR* argv[])
{
//两种方法调用构造函数
stu stu1(10,"liming");
stu *stu2 = new stu(15,"xiaohong");
cout << stu1.getName() << endl;
cout << stu2->getName() << endl;
return 0;
}
6、C++构造函数分类
1.默认构造函数
调用时不必给出实参,参数列表所有参数具有默认值
class stu{
private:
int age;
string name;
public:
stu(int a=15, string n="xiaoming");//全部具有默认参数
int getAge(){ return age; }
string getName(){ return name; }
};
//默认参数不能重复定义
stu::stu(int a /*= 15*/, string n/* = "xiaoming"*/)
{
age = a;
name = n;
}
2.复制构造函数
对象间进行复制时会调用的构造函数。
如果未定义复制构造函数,编译器会自动生成一个复制构造函数,但是这个复制构造函数只能实现表层数值的复制,并不能实现堆空间数据的复制。如果类成员中存在指针,存在动态分配堆空间这种情况,那么编译器自动生成的复制构造函数就不合适了,需要用户自己定义。
class stu{
private:
int age;
string name;
public:
stu(int a=15, string n="xiaoming");//全部具有默认参数
stu(stu &s);//不带额外参数的复制构造函数
int getAge(){ return age; }
string getName(){ return name; }
};
stu::stu(stu &s){
age = s.age;
name = s.name;
cout << "复制构造函数执行了"<<endl;
}
stu::stu(int a /*= 15*/, string n/* = "xiaoming"*/)
{
age = a;
name = n;
}
int _tmain(int argc, _TCHAR* argv[])
{
stu stu1(10,"liming");
stu stu2=stu1;//定义时赋值才会调用复制构造函数
stu2 = stu1;//不会调用复制构造函数,有编译器默认实现的方法
return 0;
}
3.深层复制构造函数
如何复制堆空间数据
class stu{
private:
int age;
string name;
char *hometown;//定义了一个指针
public:
stu(int a=15, string n="xiaoming",char* ht="hunan");//全部具有默认参数
stu(stu &s);//不带额外参数的复制构造函数
int getAge(){ return age; }
string getName(){ return name; }
};
stu::stu(stu &s){//深层复制构造函数
age = s.age;
name = s.name;
hometown = (char*)malloc(strlen(s.hometown));//分配堆空间
strcpy(hometown, s.hometown);
cout << "复制构造函数执行了"<<endl;
}
stu::stu(int a /*= 15*/, string n/* = "xiaoming"*/,char* ht)
{
int leng;
age = a;
name = n;
if (ht == NULL)
{
ht = "hunan";
}
leng = strlen(ht);
hometown = (char*)malloc(leng);
strcpy(hometown, ht);
}
int _tmain(int argc, _TCHAR* argv[])
{
stu stu1(10,"liming","beijing");
stu stu2=stu1;//定义时赋值才会调用复制构造函数
stu stu3(stu1);//同样调用复制构造函数
return 0;
}
如果使用编译器默认的复制构造函数,那么只是进行hometown指针的复制,两个对象的hometown指针将指向同一内存区,当第一个对象析构后,第二个对象将会指向一个无效区域。
7、析构函数
8、构造函数初始化列表
class stu{
private:
int age;
string name;
public:
stu(int a=15, string n="xiaoming");//全部具有默认参数
int getAge(){ return age; }
string getName(){ return name; }
};
//具有初始化参数列表的构造函数
stu::stu(int a , string n) :age(a), name(n)
{
}