1, 类和对象如何区分??异同点呢??
2, 什么是组合类,它的初始化过程呢??
3, 私有成员变量可以被对象访问吗??
4, 派生类呢??它的初始化过程呢??加入基类中带有构造函数呢??
关于类和对象,我们先来说一说:
类:简单的来讲就是有自己的属性和操作方法(行为),是一个抽象的概念,不存在于现实的时间和空间里,只是为所有的对象定义了抽象的属性与行为,如同:动物anmial是一个类,可以包含很多的个体,但就是不存在于这个世界,这是一个静态的概念,本身不携带任何数据
对象:是一个具体的,实实在在的东西,是一个动态的概念,是占用存储空间的,是一个事物,比如动物anmial类中的狗就是一个对象
异同:类是对象的抽象,对象是类的具体实例,类是抽象的,不占存储空间,对象是具体的,占用内存空间
类:动物 对象:狗
对于C++:
1. C++中的结构不仅可以包含不同类型的数据,而且还可以包含函数。
2. 结构中的数据和函数都是结构的成员,分别称为数据成员和函数成员(C++中,也称函数为成员函数,称变量为 成员变量)
3. C++类的成员函数描述了对类对象内部数据的操作方法,或者说,描述了对象的行为,因此,又将成员函数称为方法(method)或者服务(service)
4. 定义一个类的多个对象时,每一个对象拥有自己的数据成员,称为实例变量,它们各自占据不同的内存空间,但他们共用一份成员函数,这是因为同一个类的成员函数的代码是相同的,共用一份成员函数可以节省内存空间。在内存中对象的实例变量和成员函数是分开存放的,我们的成员函数通过隐藏的this指针(C++编译器自己加的)指向不同的对象来决定使用哪一个对象的数据成员
5. 类的成员变量和成员函数构成了类的接口,成员函数的定义部分称为类的实现(个人理解)
对于私有成员变量:
这意味着这些变量只能被当前类中的其他成员函数访问,外界不能访问(即为封装),不能被对象直接访问,不然可能会产生非法访问,但是如果我们把变量用public声明,那么成员函数和对象都是可以访问的,
C++规定,默认的情况下,类中的成员(数据成员,函数成员)是私有的
类的声明和定义
准确的说法是:
类的声明:一旦给出了类头,就声明了一个类,可以声明一个类但是不定义它,如:class Date;
类的定义:包含类头和类体,一旦看到类的结尾,即结束右边的花括号,这时就定义完毕
一个类仅仅被声明,那么就不能定义这种类类型的对象,因为不能确定这种类类型的大小,编译器就不知道应该分配给多少这样的存储空间,但是我们可以声明这种类类型对象的指针,因为他们与对象所占的存储空间大小无关
如果两个对象属于同一种类型,也就是说:两个对象是由同一个类声明的,那么我们可以将其中的一个对象的值(属性值)赋给另一个对象,其中数据是按位复制到第二个对象中的。但是,对象的赋值仅仅是说明两个对象的值是相等的,而这两个对象仍然是相互独立的,也就是说,修改一个对象中的值不会影响另一个对象
1,关于组合类,对象成员
下面我们来看这个程序:
class Date class Student
{ {
int day; private:
int month; int number;
int year; char name[15];
public: Date birthday;
Date(int dd, int mm, int yy); float score;
void print(); public:
} ..........;
}
一个类的成员是另一个类的对象,可以看出Student类有一个成员是类Date的对象(birthday),
我们称birthday为Student类的对象成员,而将Student类称为组合类
一般我们都知道:有构造函数的话,在创建对象的话,会默认的调用构造函数对其进行初始化,但是如果碰见上面这种情况,该如何处理呢??
#include
#include
using namespace std;
class Date
{
private:
int day, month, year;
public:
Date(int dd, int mm, int yy);
void print()
{ cout<
有一个警告:(warning: deprecated conversion from string constant to ‘char*’)
但是我们的程序是可以正常运行的,正常的对这个组合类进行初始化的
所以说:当我们对其初始化的时候应该这样做:
Student::Student(int number1, char *name1, float score1, int d1, int m1, int y1):birthday(d1, m1, y1)
{
number = number1;
strcpy(name, name1);
score = score1;
}
所以当我们进行创建类的对象时,是默认的调用了自己的构造函数,但是当成员是对象的时候,也就间接的调用了对象成员的构造函数,值得注意的是:定义组合类的构造函数时,必须将对象成员的构造函数写在后面!!!
对于类体内定义的成员函数,编译时,是按内联函数处理的,例如上面程序中类里面的print函数就是的,还有就是用inline进行声明的,编译时直接对调用处进行替换的过程,类似与c中的宏,本质就是牺牲空间换取时间
对于类体外定义的成员函数,我们必须加上类名和作用域解析运算符(“::”)
其中作用域解析运算符用来连接类名和成员名,告知编译器这个成员属于那个类
派生类的构造函数:
#include
#include
using namespace std;
class stud
{
public :
int num;
char name[10];
char sex;
public:
stud(int n, char na[], char s)
{
n = num;
strcpy(name, na);
sex = s;
}
~stud() {}
};
class student:public stud
{
private:
int age;
char addr[30];
public :
student(int n, char na[], char s, int a, char ad[]):stud(n, na, s)
{
age = a;
strcpy(addr, ad);
}
void show()
{
cout<<"num:"<
派生类构造函数名(参数表):基类构造函数名(参数表)
student(int n, char na[], char s, int a, char ad[]):stud(n, na, s)
其实,我们可以看出,派生类的构造函数是五个参数,而基类是三个参数,所以,派生类构造函数的前三个参数传递给了基类,值得注意的是,这三个参数应该在前面,不能放在后面,因为基类必须先初始化
内联函数:
首先来看函数调用的实质:其实是将程序执行转移到被调用函数所存放的内存地址,将函数执行完后,在返回到执行此函数的地方,这种转移操作需要保护现场(包括各种函数的参数的进栈操作),在被调用函数代码执行完后在恢复现场。但就是恢复现场和保护现场需要很大的资源开销。
对于一些较小的函数而言,若是调用频繁,函数的调用过程可能会比函数执行需要的系统资源更多,会更加得不偿失,所以引入了内联函数
是由编译器来将程序中出现的内联函数进行替换的过程
static:(在C++中,通过在类的成员前面加static关键字将其成员声明为静态成员,(可为:静态数据成员,静态函数成员))
静态成员变量一定应该在创建类的对象前进行定义并初始化
(int student::count = 0)其中student为类名,count为静态成员变量
一个类的静态数据成员为该类所有对象共用,不管我们创建了这个类的多少个对象,其静态数据成员在内存中只有一份拷贝,因为只有一份拷贝,所以我们经常使用(类名::)来访问静态数据成员.
当然,全局变量也可以实现数据的共享,当相对而言,封装性就不是很好了
一般来说:类的静态成员函数(加上关键字static,不能声明为const)是用来访问静态数据成员,当然也可以访问全局变量,静态成员函数不具有this指针,也就是说,静态成员函数不与某个具体的对象相联系,它只是属于该类。
调用该方法时:不会将对象的引用传递给他,所以在static方法中不可访问非static成员
友元函数:
一个类的友元函数是在该类中说明的一个非成员函数,但允许访问该类对象的所有成员,通常我们将友元函数的原型放在类的声明的public部分,并在函数声明的前面加上一个friend关键字。
如:
friend double Distance(Point &a, Point &b);在类中
定义的时候是不需要类名的。
double Distance(Point &a, Point &b)
{
}
友元函数可以直接访问对象的私有成员,节省了调用成员函数的开销,从而提高了程序的运行效率,所以引入了友元函数,当然,使用友元也就破坏了封装,降低了可维护性,因为友元函数并不是类的成员,所以在友元函数中没有this指针,因此必须通过参数来传递对象