C++面向对象程序设计的一些知识点(2)
1、C++中三种继承方式及派生类中访问控制规则
(1)、C++支持的三种继承方式是public、protected、private。C++允许一个类同时以不同的方式对不同的基类加以继承。
(2)、
| 继承方式 | 基类成员访问控制 | ||
| public | protected | private | |
| public | public | protected | no access | 
| protected | protected | protected | no access | 
| private | private | private | no access | 
注意:在派生类中,表中所述的访问控制“private”和“no access”存在很大的差别。对来自基类且在派生类中访问控制为“no access”的成员,
在派生类中是不可见的(自然,派生类的外部也不可见);对来自基类且在派生类中访问控制为“private”的子成员,在派生类内部可以访问它
们,但在派生类外部不可以访问它们。
2、派生类对象内存模型分析
(1)、程序运行时派生类对象或存在于函数栈中或存在于系统给程序分配的堆中,它是一段物理内存。
(2)、派生类与基类之间的关系是一种“is-a”的关系,否则在逻辑上必然造成混乱。
()
3、派生类对象的构造过程和析构过程
(1)、在继承方向上,先基类对象,后派生类子对象;在同一层次上,先包含类子对象,再本类子对象;如果在同一层次上存在多个包含类子
对象时,按照声明顺序来构造。
#include <iostream> using namespace std; class EmbededA_Root
{
public:
EmbededA_Root()
{
cout << "1_a:constructing embedded sub object A.\n";
}
~EmbededA_Root()
{
cout << "1_a:destructing embedded sub object A.\n";
}
private:
};
class EmbededB_Root
{
public:
EmbededB_Root()
{
cout << "1_b:constructing embedded sub object B.\n";
}
~EmbededB_Root()
{
cout << "1_b:destructing embedded sub object B.\n";
}
private:
};
class RootBase
{
public:
RootBase():embedA(), embedB()
{
cout << "1:constructing root base sub object.\n";
}
~RootBase()
{
cout << "1:destructing root base sub object.\n";
}
private: EmbededB_Root embedB;
EmbededA_Root embedA;
};
class Base:RootBase
{
public:
Base()
{
cout << "2:constructing base sub object.\n";
}
~Base()
{
cout << "2:destructing base sub object.\n";
}
private:
};
class Derived:public Base
{
public:
Derived()
{
cout << "3:constructing derived sub object.\n";
}
~Derived()
{
cout << "3:destructing derived sub object.\n";
}
private:
}; int main()
{
{
Derived d;
}
int c;
cin >> c;
return ;
}
运行结果是:
如果将类RootBase中的embedA和embedB声明顺序换一下的话,则结果是:

4、跨类的同名成员
(1)、派生类属性会隐藏其基类的同名属性,此时区分它们的方法是加上作用域限定符,即“积累名::属性名”。
(2)、在非多态的情况下,派生类同名函数永远使基类同名函数隐藏起来(即使成员函数的特征表不同)。
5、基类对象与派生类对象之间的转换
(1)、用派生类对象给基类对象赋值或者用派生类初始化基类引用;此时是安全的,通常我们也应该重新编写赋值运算符的重载。
(2)、用基类对象给派生类对象赋值;此时是危险的,不应该这么做。
(3)、基类指针指向派生类对象地址;基类指针至少包含指针值和允许访问范围这样两个属性,而且此时基类指针允许访问的范围仅限于派生类对象子对象。
(4)、派生类指针指向基类对象;此时是危险的,不应该这么做。
(5)、C++提供的类型转换运算符。
6、多继承
(1)、非虚拟基类多继承;
#include <iostream> using namespace std; class Base
{
public:
Base(int a)
{
this->a = a;
cout << "common base sub object being constructed.\n";
}
void show()
{
cout << a << endl;
}
~Base()
{
cout << "deleting common base sub object.\n";
}
private:
int a;
};
class B1:public Base
{
public:
B1(int a, int b1):Base(a)
{
this->b1 = b1;
cout << "base1 sub object being constructed.\n";
}
void showBase()
{
show();
}
~B1()
{
cout << "deleting base1 sub object.\n";
}
private:
int b1;
};
class B2:public Base
{
public:
B2(int a, int b2):Base(a)
{
this->b2 = b2;
cout << "base2 sub object being constructed.\n";
}
void showBase()
{
show();
}
~B2()
{
cout << "deleting base2 sub object.\n";
}
private:
int b2;
};
class D:public B2, public B1
{
public:
D(int a1, int b1, int a2, int b2, int d):B1(a1, b1), B2(a2, b2)
{
this->d = d;
cout << "derived sub object being constructed.\n";
}
void showB1Base()
{
B1::showBase();
}
void showB2Base()
{
B2::showBase();
}
~D()
{
cout << "deleting derived sub object.\n";
}
private:
int d;
}; int main()
{
{
D d(, , , , );
d.B1::show();
d.B2::show();
d.B1::showBase();
d.B2::showBase();
d.showB1Base();
d.showB2Base();
}
int c;
cin >> c;
return ;
}
此时基类对象在派生类对象中占有一个独立的内存空间。
(2)、虚拟基类多继承;
#include <iostream> using namespace std; class Base
{
public:
Base(int a)
{
this->a = a;
cout << "common base sub object being constructed.\n";
}
void show()
{
cout << a << endl;
}
~Base()
{
cout << "deleting common base sub object.\n";
}
private:
int a;
};
class B1:virtual public Base
{
public:
B1(int a, int b1):Base(a)
{
this->b1 = b1;
cout << "base1 sub object being constructed.\n";
}
void showBase()
{
show();
}
~B1()
{
cout << "deleting base1 sub object.\n";
}
private:
int b1;
};
class B2:virtual public Base
{
public:
B2(int a, int b2):Base(a)
{
this->b2 = b2;
cout << "base2 sub object being constructed.\n";
}
void showBase()
{
show();
}
~B2()
{
cout << "deleting base2 sub object.\n";
}
private:
int b2;
};
class D:public B1, public B2
{
public:
D(int a, int b1, int b2, int d):B1(a, b1), B2(a, b2), Base(a)
{
this->d = d;
cout << "derived sub object being cosntructed.\n";
}
void showB1Base()
{
B1::showBase();
}
void showB2Base()
{
B2::showBase();
}
~D()
{
cout << "deleting derived sub object.\n";
} private:
int d;
}; int main()
{
{
D d(, , , ); d.showB1Base();
d.showB2Base();
}
int c;
cin >> c;
return ;
}
此时基类子对象只包含一个。
7、继承综合应用实例
类关系UML图如图:

代码:
#include <iostream> using namespace std; class Employee
{
public:
Employee(char *name)
{
no = companyEmployee++;
grade = ;
pName = new char[strlen(name) + ];
strcpy(pName, name);
totalPay = 0.0;
}
~Employee()
{
delete [] pName;
}
public:
void pay(){}
void promote(int increment)
{
grade += increment;
}
void displayInfo(){}
protected:
char *pName;
int no;
int grade;
double totalPay;
static int companyEmployee;
private:
};
int Employee::companyEmployee = ; // 静态变量初始化 class Technician:public Employee
{
public:
Technician(char *name, int workHours = ):Employee(name)
{
rate = ; // 100元/小时
this->workHours = workHours;
}
void setWorkhours(int workHours)
{
this->workHours = workHours;
}
void pay()
{
totalPay = workHours*rate;
}
void displayInfo()
{
promote();
cout << "兼职技术人员:" << pName << ",编号:" << no
<< ",级别:" << grade << ",已付本月工资:"
<< totalPay << endl;
}
private:
double rate;
int workHours;
};
class SaleMan:virtual public Employee
{
public:
SaleMan(char *name, int sales = ):Employee(name)
{
ratio = 0.004;
this->sales = sales;
}
void setSales(double sales)
{
this->sales = sales;
}
void pay()
{
totalPay = sales*ratio;
}
void displayInfo()
{
promote();
cout << "推销员:" << pName << ",编号:" << no
<< ",级别:" << grade << ",已付本月工资:"
<< totalPay << endl;
}
protected:
double sales;
double ratio;
};
class Manager:virtual public Employee
{
public:
Manager(char *name, int monthlyPay = ):Employee(name)
{
this->monthlyPay = monthlyPay;
}
void setMonthlyPay(double monthlyPay)
{
this->monthlyPay = monthlyPay;
}
void pay()
{
totalPay = monthlyPay;
}
void displayInfo()
{
promote();
cout << "经理:" << pName << ",编号:" << no
<< ",级别:" << grade << ",已付本月工资:"
<< totalPay << endl;
}
protected:
double monthlyPay;
};
class SaleManager:public SaleMan, public Manager
{
public:
SaleManager(char *name):SaleMan(name), Manager(name), Employee(name)
{
monthlyPay = ;
ratio = 0.002;
}
void pay()
{
totalPay = monthlyPay + sales*ratio;
}
void displayInfo()
{
promote();
cout << "销售经理:" << pName << ",编号:" << no
<< ",级别:" << grade << ",已付本月工资:"
<< totalPay << endl;
}
private:
}; int main()
{
Technician t("zhang san");
t.setWorkhours();
t.pay();
t.displayInfo(); SaleManager sm("li si");
sm.setMonthlyPay();
sm.setSales();
sm.pay();
sm.displayInfo();
int c;
cin >> c;
return ;
}
C++面向对象程序设计的一些知识点(2)的更多相关文章
- C++面向对象程序设计的一些知识点(5)
		摘要:运算符能给程序员提供一种书写数学公式的感觉,本质上运算符也是一种函数,因此有类内部运算符和全局运算符之分,通过重载,运算符的“动作”更加有针对性,编写代码更像写英文文章. 1.C++标准允许将运 ... 
- C++面向对象程序设计的一些知识点(4)
		摘要:累继承可以实现源代码重用,模板技术也可以达到同样的目的.模板可以分为函数模板和类模板,其共同点是允许参数类进行类型化,编译器根据程序员传递的具体类型,又把函数模板实例化为具体函数,把类模板实例化 ... 
- C++面向对象程序设计的一些知识点(3)
		摘要:多态性提供一组统一的调用接口函数,依据这些条用接口函数具体对象的不同,同一名字的函数会有不同的行为. 1.重载与隐藏 (1).对同一作用域中的同名函数,如果它们的函数特征标不同,那么它们就形成一 ... 
- C++面向对象程序设计的一些知识点(1)
		1.函数重载而不出错是有条件的: (1).这些函数位于同一域内,如同一类中.同一文件中. (2).这些同名函数具有不同的参数特征标(特征标是指形參的个数.类型.排列顺序等). 2.引用特性(与指针对比 ... 
- 对面向对象程序设计(OOP)的认识
		前言 本文主要介绍面向对象(OO)程序设计,以维基百科的解释: 面向对象程序设计(英语:Object-oriented programming,缩写:OOP),指一种程序设计范型,同时也是一种程序开发 ... 
- 20162317袁逸灏 第八周实验报告:实验二 Java面向对象程序设计
		20162317袁逸灏 第八周实验报告:实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 ... 
- 2018-2019-2 20175217 实验二《Java面向对象程序设计》实验报告
		一.实验报告封面 课程:Java程序设计 班级:1752班 姓名:吴一凡 学号:20175217 指导教师:娄嘉鹏 实验日期:2019年4月15日 实验时间:--- 实验序号:实验二 实验名称:Jav ... 
- 20175315 实验二《Java面向对象程序设计》实验报告
		20175315 实验二<Java面向对象程序设计>实验报告 一.实验内容及步骤 1.初步掌握单元测试和TDD 单元测试 任务一:三种代码 用程序解决问题时,要学会写以下三种代码: 伪代码 ... 
- 2018-2019-2 20175202实验二《Java面向对象程序设计》实验报告
		2018-2019-2 20175202实验二<Java面向对象程序设计>实验报告 一.实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初 ... 
随机推荐
- vue provide和inject使用
			provide和inject使用场景也是组件传值,尤其是祖父组件--孙组件等有跨度的组件间传值,单向传值(由provide的组件传递给inject的组件). provide 选项应该是一个对象或返回一 ... 
- [Done][DUBBO] dubbo Thread pool is EXHAUSTED!
			异常信息: com.alibaba.dubbo.remoting.ExecutionException: class com.alibaba.dubbo.remoting.transport.disp ... 
- Loadrunner脚本回放 场景运行过程中常见错误分析
			问题一:Loadrunner超时错误问题描述 Loadrunner超时错误:在录制Web协议脚本回放时超时情况经常出现,产生错误的原因也有很多,解决的方法也不同. 问题现象Error -27728: ... 
- Linux 调优方案, 修改最大连接数-ulimit
			Linux对于每个用户,系统限制其最大进程数.为提高性能,可以根据设备资源情况,设置各linux 用户的最大进程数 可以用ulimit -a 来显示当前的各种用户进程限制.下面我把某linux用户的最 ... 
- 原创:微信小程序调用PHP后台接口,解析纯html文本
			---效果图片预览--- 1.微信js动态传参:wx.request({ url: 'https://m.****.com/index.php/Home/Xiaoxxf/activ ... 
- PHP-FastCGI详解
			一.什么是 FastCGI FastCGI是一个可伸缩地.高速地在HTTP server和动态脚本语言间通信的接口.多数流行的HTTP server都支持FastCGI,包括Apache.Nginx和 ... 
- Matlab调用返回游标的存储过程的分析和处理
			2.Matlab调用Oracl带游标参数输出的存储过程 笔者也是将工作之中遇到的问题进行了搜集与整理,才完成该文的编写,希望能帮助到有需要的朋友. 2.1.PLSQL中的存储过程 PROCEDURE ... 
- inet_ntoa 的一个小问题
			一个简单点的阻塞式tcp服务器如下所示: #include <stdio.h> #include <string.h> #include <sys/socket.h> ... 
- 使用springboot遇到的的异常
			Unregistering JMX-exposed beans on shutdown <dependency> <groupId>org.springframework.bo ... 
- 常用JS技巧[转]
			作者:72妃 事件源对象 event.srcElement.tagName event.srcElement.type 捕获释放 event.srcElement.setCapture(); even ... 
