C语言进阶到C++知识点补充
1、思想:由于C语言的面向过程进阶到C++的面向对象。
2、新特性:C++实现封装、继承、多态
3、新知识点:类和对象、继承、重载、多态、数据封装、异常处理、模板
1、引用
阅读本节你将掌握的知识点
C++引用
引用变量是一个别名。他是某个已经存在的变量的另外一个名字。
一旦把引用初始化为某个变量,就可以使用该引用名称或者变量名称来指向变量。
C++引用和指针
三个不同点:
1)不存在空引用,引用必需连接到一个合法内存
2)一旦引用被初始化一个对象,就不能被指到另外一个对象,指针可以再任何时候指向到另一个对象
3)引用必须在创建的时候被初始化,指针可以在任何时候进行初始化。
int i = 17;
int & r = i;
double & s = d;
引用的使用场景
1、引用作为函数的参数列表
引用作为参数传给函数,这比传一般的参数更加安全
2、引用作为返回值
可以从C++函数中返回引用,就像返回其他数据类型一样通过用引用来替代指针,使得C++程序更容易维护,C++返回一个引用,方式与返回一个指针类似、当函数返回一个引用的时候,则会返回一个指向返回值的隐式指针,这样,函数就可以放在赋值语句的左边。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
//引用传参
void swap(int &x,int &y)
{
int temp;
temp = x;
x = y;
y = temp;
}
//把引用作为返回值
double vals[] = {10.1,12.6,33.1,24.1,50.0};
double &setValues(int i){
double &ref = vals[i];
return ref; //返回第一个元素的引用,ref是一个引用变量,ref引用vals[i]
}
//当返回一个引用的时候,注意对象不能超过作用域,返回一个局部变量的引用是不合法的,但是可以返回一个静态变量的引用。
int &func(){
int q;
//! return q; //在编译时发生错误
static int x;
return x;
}
int main(int argc, char **argv)
{
cout <<"改变之前的值"<<endl;
for (int i = 0; i < 5; i++)
{
cout<<"vals["<<i<<"]"<<vals[i]<<endl;
}
setValues(1) = 20.23;//改变第二个元素
setValues(3) = 70.8; //改变第四个元素
cout <<"改变之后的值"<<endl;
for (int i = 0; i < 5; i++)
{
cout<<"vals["<<i<<"]"<<vals[i]<<endl;
}
return 0;
}
2、类和对象
阅读本节你将掌握的知识点
1、面向对象的编程思想
新定义类的都以class类为蓝本。
2、类的定义、类中的成员和方法
3、构造函数和析构函数
4、友元函数
5、拷贝构造函数
是一种特殊的构造函数,它在创建对象时,使用同一个类中之前创建的对象来初始化新创建的对象。拷贝构造函数常用于:
1、通过使用另外一个同类型的对象初始化新创建的对象
2、复制对象把它作为参数传递给函数
3、复制对象,并从函数返回这个对象
如果类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。
拷贝构造函数的常用格式如下:
classname (const classname &obj){
//构造函数的主体
}
6、this指针 && 指向类成员的指针
每个对象都可通过this指针来访问自己的地址,this是所有成员函数的隐含参数,因此在成员函数的内部,可以用来调用对象。
友元函数没有this指针,因为友元函数没不是类的成员,只有成员函数才有this指针。
7、访问权限 三类
1)public成员类外可以直接访问
2)private成员类外无法直接访问,如赋值、初始化等操作,需要借助函数类外实现
3)protect成员类外无法直接访问,不过可以通过子类继承来访问父类成员。
私有成员和保护成员不能直接用成员运算符访问!!!
#include<iostream>
using namespace std;
class box
{
public:
double length;//成员
double height;
double width;
double get(void);//方法
void set(double len,double wid,double height);
friend int getboxlength(box box);//友元函数:可以访问在类外访问类内成员
bool compare(box boxx);
int getlength();
private:
int *ptr;
public:
box(){
cout<<"none arguments"<<endl;
}
box(int len){ //构造函数
ptr = new int;
*ptr = len;
}
box(const box &obj); //拷贝构造函数
~box(){ //析构函数
cout<<"release mem"<<endl;
delete ptr;
}
};
//this指针的示例
bool box::compare(box boxx)
{
if (this->length>boxx.length)
{
cout<<"go"<<endl;
return true;
}
else return false;
}
int box::getlength(){
return *ptr;
}
//拷贝构造函数
box::box(const box &obj)
{
cout<<"拷贝构造函数的调用"<<endl;
ptr = new int;
*ptr = *obj.ptr;//拷贝的数值
}
void dispaly(box obj){
cout<<"获得的长度为:"<<obj.getlength()<<endl;
}
//友元函数
int getboxlength(box box)
{
return box.length;
}
double box::get(void)
{
return length*width*height;
}
void box::set(double len,double wid,double hei)
{
length = len;
width = wid;
height = hei;
}
int main(){
box box1(10);
box box2 = box1;
box1.length = 3;
box1.height = 4;
box1.width = 5;
box2.length = 1;
box1.compare(box2);
box *ptr;
ptr = &box1;
cout<<"ptr->length = "<<ptr->height<<endl;
double value = 0.0;
//cout<<"友元函数的使用:"<<getboxlength(box1)<<endl;//友元函数
return 0;
}
3、继承
阅读本节你将掌握的知识点
1、类的继承
public、private、protected
访问控制和继承:
派生类可以访问基类中的所有非私有成员,因此,基类成员如果不想被派生类的成员函数访问,应该在基类中声明为private。protected类可以在派生类中被访问。
访问权限的类型总结:
public protected private
同一个类 y y y
派生的类 y y n
外部的类 y n n
一个派生类继承了所有的基类的方法,但是如下情况除外:
1)基类的构造函数、析构函数、拷贝构造函数
2)基类的重载运算符
3)基类的友元函数
通常还是使用 public继承方式
2、多继承 一个子类可以有多个父类,它继承了多个父类的特性。
class <派生类名称>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
}
#include<iostream>
using namespace std;
//基类1
class base{
public:
void setwidth(int wid);
void setlength(int len);
protected:
int length;
int width;
};
void base::setlength(int len)
{
length = len;
}
void base::setwidth(int wid)
{
width = wid;
}
//基类2
class CalcCost{
public:
int getCost(int area)
{
return area*70;
}
};
//派生类
class CalcArea:public CalcCost,public base{
public:
int getArea()
{
return length * width;
}
};
int main(){
CalcArea Rect;
int area;
Rect.setlength(5);
Rect.setwidth(7);
area = Rect.getArea();
//输出面积
cout<<"面积为:"<<Rect.getArea()<<endl;
//输出花费
cout<<"总花费为:"<<Rect.getCost(area)<<endl;
return 0;
}
4、重载运算符和重载函数
阅读本节你将掌握的知识点
1、运算符重载的实现
2、运算符重载的列表
3、可重载运算符和不可重载运算符
重点记忆不可重载的运算符:
.:成员访问运算符
.* ->* 成员指针访问运算符
:: : 域运算符
sizeof : 长度运算符
? 条件运算符
# 预处理运算符
4、重载函数的实现是函数名相同,函数内的参数不同,代码被编译执行后,编译器会自动找到对应的重载函数。
#include<iostream>
using namespace std;
class Box
{
public:
double getValue(void){
return length*breadth*height;
}
void setLength(double len)
{
length=len;
}
void setBreadth(double bre)
{
breadth=bre;
}
void setHeight(double hei)
{
height = hei;
}
//重载运算符 括号中的是右值,双目运算符的重载
Box operator+(const Box& b)
{
Box box;
box.length = this->length+ b.length;
box.height = this->height+ b.height;
box.breadth = this->breadth+ b.breadth;
return box;
}
private:
double length;
double height;
double breadth;
};
int main(){
Box box1;
Box box2;
Box box3;
double volume = 0.0;
//box1
box1.setLength(6.0);
box1.setBreadth(7.0);
box1.setHeight(5.0);
//box2
box2.setLength(12.0);
box2.setBreadth(13.0);
box2.setHeight(10.0);
//box1
volume = box1.getValue();
cout<<"volume of box1 : "<<volume<<endl;
//box2
volume = box2.getValue();
cout<<"volume of box2 : "<<volume<<endl;
//box3:两个对象相加得到BOX3
box3 = box2 + box1;
volume = box3.getValue();
cout<<"volume of box3 : "<<volume<<endl;
return 0;
}
5、多态
阅读本节你将掌握的知识点
1、多态:类之间存在层次结构,并且类之间是通过继承关联的时候,就会用到多态,
C++多态意味着调用成员函数的时候,会根据调用成员函数的对象的类型不同来执行不同的操作。
2、关键字virtual的使用。
1)虚函数 是基类中使用virtual声明的函数。
在派生类中重新定义基类中定义的虚函数时,告诉编译器不要静态链接到该函数。
需要让程序再任一点可以根据所调用的对象类型来选择调用的函数,这种操作称之为动态链接或者后期绑定。
2)纯虚函数:想在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是又不能在虚函数中给出有意义的实现。
虚函数和纯虚函数:虚函数在基类中已经实现了方法, 但是派生类不调用,纯虚函数时基类中没有实现方法,派生类自主实现方法。
#include<iostream>
using namespace std;
class Shape{
protected:
int width, height;
public:
Shape(int a = 0,int b = 0)
{
width = a;
height = b;
}
//基类中使用virtual 关键字
virtual int area()
{
cout<<"Parent class area : "<<endl;
return 0;
}
};
class Rectangle:public Shape{
public:
Rectangle(int a = 0,int b = 0):Shape(a,b){ }
int area()
{
cout<<"Rectangle class area : "<<endl;
return (width*height);
}
};
class Triangle:public Shape{
public:
Triangle(int a = 0,int b = 0):Shape(a,b){ }
int area()
{
cout<<"Triangle class area : "<<endl;
return (width*height/2);
}
};
int main(){
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
//存储矩形的地址
shape = &rec;
//调用矩形的求面积函数area
shape->area();
//存储三角形的地址
shape = &tri;
//调用三角形的求面积函数area
shape->area();
return 0;
}