继承的实现
在C语言的结构体里可以有构造函数、析构函数,可以有普通变量、静态变量,也可以有静态函数等等(访问权限与类不同,默认是public),面向对象封装特征基本上都实现了,然而,在继承方面结构体就无能为力了。
struct stu
{
private: //私有属性,只能成员函数访问
char *name;
int age;
public:
static int c;
static void fun(int add)//静态函数,可以通过结构体名访问stu::fun(20); 只能访问静态变量
{
c +=add;
}
public:
stu() //构造函数
{
}
~stu()
{
}
};
int stu::c=20; //初始化静态变量
利用已有类,通过派生的方式定义一个新类,该类继承已有类的属性和行为,称为继承。继承和派生体现了类的层次结构,表现了事物从一般到具体的认识过程。语法:
class 派生类名 :public | private |protected 父类名
{
........... //派生类新增的属性和行为
}
public 继承:最常用方式,父类的成员访问权限在派生类中保持不变
private 继承:父类中私有的公有和保护成员在派生类中变成私有
protected 继承:父类中私有的公有和保护成员在派生类中变成保护
关于成员访问权限,如下例:
#include<iostream>
using namespace std;
class person
{
private:
int id;
protected:
int testid;
public:
int age;
char *name;
int getid()
{
return id;
}
void setid(int _id)
{
id=_id;
}
};
class student:public person
{
public:
int stu_no;
void setid(int _id)
{
person::setid(_id);
}
void settestid(int _id)
{
testid=_id;
}
int gettestid()
{
return testid;
}
};
int main()
{
student s;
s.age=20;
s.setid(30);
cout<<s.getid()<<endl;
s.settestid(60);
cout<<s.gettestid()<<endl;
return 0;
}
1、student s;s 不能直接访问 id 和 testid ( s.id=20 s.testid=30 都是错误的),公用成员变量可以直接访问 (s.age=20 ; 正确)
2、要访问继承于父类的私有变量,派生类 student 的函数也不能直接调用,而必须使用父类的公用或者保护类型函数; student 类通过继承的 getid (父类函数) 来读私有变量id; setid也可以类似完成,也可以像上面代码重写setid 注意调用父类函数的时候要带作用域 person::setid(_id);
3、继承于父类的保护类型变量testid ,可以在派生类的函数中使用,不需要通过父类函数访问;
4、公用、私有、保护继承父类把父类的成员变量和函数进行了权限的变更,语法与上例类似;
5、建议初学者可以暂时忽略数据封装的一些细节,在涉及命名空间等时再注。继承一般用的是公用。
派生类的构造函数
派生类生成对象的时候,先调用父类构造函数,然后是派生类构造函数,析构的时候则相反,先调用派生类析构函数,再调用父类析构函数:
#include<iostream>
using namespace std;
class person
{
public:
person()
{
cout<<"person constructing .....\n";
}
~person()
{
cout<<"person deconstructing .....\n";
}
};
class student:public person
{
public:
student()
{
cout<<"student constructing .....\n";
}
~student()
{
cout<<"student deconstructing .....\n";
}
};
int main()
{
student s;
return 0;
}
构造、析构函数一般不用 private :私有意味着不能在该类外调用构造和析构函数,也就说没办法生成父类对象(派生类要先调用父类构造函数,当然也不能实例化),某些特殊情况下使用私有构造函数来限制用类的实例(唯一对象类等等)。
派生类与父类构造函数参数不同的情况:
class person
{
public:
int age;
char *name;
person(int _age,char *_name)
{
age=_age;
name=_name;
}
};
class student:public person
{
public:
student()
{
}
};
int main()
{
student s;
return 0;
}
student 的构造函数只能调用父类默认的空构造函数,在改写父类构造函数后,系统不会自带一个无参构造函数,所以,以上代码是错误的,通过以下方法解决:
student(int _age,char *_name):person(_age,_name)
{
}
构造函数执行前,调用父类的带参构造函数。否则会调用默认的无参构造函数。
多重继承
多重继承是被诟病的一个特性,C++允许多重继承,但是尽量避免使用。多重继承会提升问题的复杂度。很多其他高级语言抛弃了多重继承,通过单继承类、多实现接口的方式把继承的多样性限制在接口,以此来降低程序的复杂度。
C++多继承例子:
#include<iostream>
using namespace std;
class person
{
public:
person()
{
cout<<"person constructing .....\n";
}
~person()
{
cout<<"person deconstructing .....\n";
}
};
class human
{
public:
human()
{
cout<<"human constructing .....\n";
}
~human()
{
cout<<"human deconstructing .....\n";
}
};
class student:public person,public human
{
public:
student()
{
cout<<"student constructing .....\n";
}
~student()
{
cout<<"student deconstructing .....\n";
}
};
int main()
{
student s;
return 0;
}