C++系列笔记(四)

简介: C++系列笔记(四)

导读21天学通C++》这本书通过大量精小短悍的程序详细而全面的阐述了C++的基本概念和技术,包括管理输入/输出、循环和数组、面向对象编程、模板、使用标准模板库以及创建C++应用程序等。这些内容被组织成结构合理、联系紧密的章节,每章都可在1小时内阅读完毕,都提供了示例程序清单,并辅以示例输出和代码分析,以阐述该章介绍的主题。 本文是系列笔记的第四篇,欢迎各位阅读指正! 

参数是引用,如果不加&的话就是平常参数,也就是传值参数。传值参数,如果实参在函数中被修改时,外面的这个变量并不会改变。引用参数,也就是在形参加上&,如果实参在函数中被修改的同时,外面的这个变量也会被修改。例:

inta=10;
voidadd1(intx)
{
x++;
}
add1(a);

执行完之后a还是10。

inta=10;
voidadd2(int&x)
{
x++;
}
add2(a);

执行完之后a=11。

禁止在栈中实例化的类

数据库类把析构函数设置为私有,只能使用new在自由储存区中创建其对象。如下代码:

classMonsterDB{
private:
~MonsterDB( ) {};
public:
staticvoidDestroyInstance(MonsterDB*pInstance)
    {
deletepInstance;
    }
//……imagine a few other methods};
intmain()
{
MonsterDB*pMyDatabase=newMonsterDB();
MonsterDB :: DestroyInstance(pMyDatabase);
return0;
}

this指针

在类中,关键字this包含当前对象的地址,换句话说,其值为&object。

结构不同于类的地方

关键字struct来自于c语言,它与类极其相似。除非指定了,结构中的成员默认为公有,而类默认为私有;结构默认以公有方式继承,而类默认以私有方式继承。

声明友元函数

不能从外部访问类的私有数据成员和方法,但这条规则不适用于友元类和友元函数。要声明友元类和友元函数,可使用关键字friend,如下述所示。

#include<iostream>#include<string>usingnamespacestd;
classHuman{
private:
stringName;
intAge;
friendvoidDisplayAge(constHuman&Person);
public:
Human(stringInputName, intInputAge)
        {
Name=InputAge;
Age=InputAge;
        }
};
voidDisplayAge(constHuman&person)
{
cout<<person.Age<<endl;
}
intmain()
{
HumanFirstMan("Adam", 25);
cout<<"Accessing private member age via:";
DisplayAge(FirstMan);
return0;
}

输出为:

Accessingprivatememberagevia:25

与函数一样,也可以将外部类指定为可信任的朋友。

friendclassUtility;
classUtility{
//code here;}

实现继承

基类比如鸟,将定义鸟的基本属性,如有羽毛和翅膀等等;派生类为乌鸦、鹦鹉等等将继承这些属性并进行定制。有些派生类能继承两个基类,这种称为多继承。

C++派生语法

//declaring a super classclassBase{
//……base class members};
//declaring a sub_classclassDerived: acess-specifierBase{
//……derived class members};

其中acess-specifier可以是public(这是最常见的,表示派生类是一个基类)、private或protected(表示派生类有一个基类)。示例代码:

#include<iostream>#include<string>usingnamespacestd;
classFish{
public:
boolFreshWaterFish;
voidSwim()
        {
if (FreshWaterFish)
cout<<"swims in lake"<<endl;
elsecout<<"swims in sea"<<endl;
        }
};
classTuna :publicFish{
public:
Tuna()
        {
FreshWaterFish=false;
        }
};
classCarp :publicFish{
public:
Carp()
        {
FreshWaterFish=true;
        }
};
intmain()
{
CarpmyLunch;
TunamyDinner;
cout<<"my food to swim"<<endl;
cout<<"lunch:";
myLunch.Swim();
cout<<"Dinner:";
myDinner.Swim();
return0;
}

输出为:

myfoodtoswimlunch:swimsinlakeDinner:swimsinsea

访问限定符protected

将属性声明为protected时,相当于允许派生类和友元类访问他,但禁止在继承层次结构外部(包括main()访问他)。

classFish{
protected:
boolFreshWaterFish;
//code here}

基类初始化——向基类传递参数。如下面代码所示:

classBase{
public:
Base(intSomeNumber)  //overload constructor    {
//Do Something with Somenumber    }
};
classDerived : publicBase{
public:
Derived(): Base(25)  //instance class Base with argument 25{
//derived class constructor code}
};

上述代码改一下:

//基类改一下public :
Fish(boolIsFreshWater) : FreshWaterFish(IsFreshWater) {}
//继承类Tuna改一下public:
Tuna() : Fish(false) {}
//继承类Carp改一下public:
Carp() : Fish(true) {}

在派生类中覆盖基类的方法

如果派生类实现了从基类继承的函数,且返回值和特征值相同,就相当于覆盖了基类的方法,即派生类有一个和基类一模一样的函数,则程序运行是输出了派生类的函数结果。

调用基类中被覆盖的方法

1)如果要在main()中调用Fish::Swim(),需要使用作用域解析符(::)把上述的代码改一下就可以。

//在Carp类中voidSwim()
{
cout<<"Carp swims is too low"<<endl;
Fish::Swim();
}
//在main()函数中cout<<"Dinner:";
myDinner.Fish::Swim();

2)在Carp类中,使用关键字using解除对Fish::Swim()的隐藏

//在Carp类中classCarp{
public:
usingFish::Swim;  //去除基类隐藏的方法}

3)在Carp类中,覆盖Fish::Swim()的所有重载版本。

析构顺序和构造顺序

继承时,构造函数和析构函数的调用顺序 1、先调用父类的构造函数,再初始化成员,最后调用自己的构造函数 2、先调用自己的析构函数,再析构成员,最后调用父类的析构函数 3、如果父类定义了有参数的构造函数,则自己也必须自定义带参数的构造函数 4、父类的构造函数必须是参数列表形式的 5、多继承时,class D: public Base2, Base1, Base的含义是:class D: public Base2, private Base1, private Base,而不是class D: publicBase2, public Base1, public Base6.多继承时,调用顺序取决于class D: public Base2, public Base1, public Base的顺序,也就是先调用Base2,再Base1,再Base。但是有虚继承的时候,虚继承的构造函数是最优先被调用的。

私有继承:private

即便是Base类的公有成员和方法,也只能被Derived类使用,而无法通过Derived实例来使用他们。

保护继承:protected

保护继承与私有继承的相似之处:1)他也表示has-a关系 2)他也让派生类能够访问基类的所有公类和保护成员 3)在继承结构层次外面,也不能通过派生类实例访问基类的公有成员 随着继承结构的加深,保护继承与私有继承有些不同

classDerived2:protectedDerived{
//can acess menber of Base};

在保护继承层次结构中,子类的子类(Derived)能够访问Base类的公有成员。将Base类作为子类的私有成员被称为组合或聚合,如下面代码所示:

classCar{
private:
MotorheartOfcar;
public:
voidMove()
{
heartOfca.SwitchInginition();
//code here;]
];

这能够轻松在Car类中添加Motor成员而无需改变继承结构层次

切除问题

DerivedobjectDerived;
BaseobjectBase=objectDerived;

或者:

voidFunuseBase(BaseInput)
……DerivedobjectDerived;
FunuseBase(objectDerived);

上述代码都将Derived对象复制给Base对象,一个是显示复制,一个是通过传递函数。在这种情况下,编译器将只会复制objectDerived的Base部分,即不是整个对象,而是Base能容纳的部分。这种无意间裁剪数据,导致Derived变成Base的行为称为切除(slice)

多继承

C++允许继承多个基类

classDerived : acess-specifierBase1,cess-specifierBase2,……{
//class menbers};
相关文章
|
2月前
|
Java 编译器 C++
C++入门指南:类和对象总结笔记(下)
C++入门指南:类和对象总结笔记(下)
30 0
|
2月前
|
存储 编译器 C语言
C++入门: 类和对象笔记总结(上)
C++入门: 类和对象笔记总结(上)
34 0
|
4月前
|
设计模式 安全 编译器
Effective C++55 笔记
Effective C++55 笔记
21 0
|
7月前
|
消息中间件 存储 前端开发
[笔记]C++并发编程实战 《四》同步并发操作(三)
[笔记]C++并发编程实战 《四》同步并发操作(三)
|
3天前
|
安全 Java 程序员
【C++笔记】从零开始认识继承
在编程中,继承是C++的核心特性,它允许类复用和扩展已有功能。继承自一个基类的派生类可以拥有基类的属性和方法,同时添加自己的特性。继承的起源是为了解决代码重复,提高模块化和可维护性。继承关系中的类形成层次结构,基类定义共性,派生类则根据需求添加特有功能。在继承时,需要注意成员函数的隐藏、作用域以及默认成员函数(的处理。此外,继承不支持友元关系的继承,静态成员在整个继承体系中是唯一的。虽然多继承和菱形继承可以提供复杂的设计,但它们可能导致二义性、数据冗余和性能问题,因此在实际编程中应谨慎使用。
5 1
【C++笔记】从零开始认识继承
|
2月前
|
编译器 C语言 C++
C++入门指南:类和对象总结笔记(中)
C++入门指南:类和对象总结笔记(中)
49 0
|
3月前
|
机器学习/深度学习 算法 编译器
【C++】自学终极笔记
【C++】自学终极笔记
150 0
|
4月前
|
存储 算法 C++
《C++ STL开发技术引导》 第五章-C++ STL泛化技术分析笔记
《C++ STL开发技术引导》 第五章-C++ STL泛化技术分析笔记
|
4月前
C++2.0(C++11) 笔记 二
C++2.0(C++11) 笔记 二
20 0
|
4月前
|
编译器 容器
C++11 (C++2.0)笔记 一
C++11 (C++2.0)笔记 一
33 0