重载
定义
函数名相同,但形参的个数、数据类型、顺序中有一个不同,调用函数时C++会区分出来,进而执行不同函数的功能,这就是函数重载。
形参个数不同
int sum(int v1, int v2)
{
return v1 + v2;
}
int sum(int v1, int v2, int v3)
{
return v1 + v2 + v3;
}
int main()
{
cout << sum(10 , 20) << endl;//会自动识别两个形参的sum函数,返回30
cout << sum(10 , 20 , 30) << endl;//会自动识别三个形参的sum函数,返回60
getchar();
return 0;
}
形参类型不同
int sum(int v1, int v2)
{
return v1 + v2;
}
double sum(double v1, double v2)
{
return v1 + v2;
}
int main()
{
cout << sum(10 , 20) << endl;//会自动识别int类型的sum函数,返回30
cout << sum(20.0 , 20.0) << endl;//会自动识别double类型的sum函数,返回40.0
getchar();
return 0;
}
顺序不同
void function(int v1, double v2)
{
cout << "int v1, double v2" << endl;
}
void function(double v2, int v1)
{
cout << "double v2, int v1" << endl;
}
int main()
{
function(4, 4.0);//会自动识别先int后double的函数
function(4.0, 4);//会自动识别先double后int的函数
getchar();
return 0;
}
以上情况是函数重载比较常见的情况。
函数重载的本质
C++编译器采用了一种name mangling的底层技术, 使得C++编译器默认会对函数名进行改编、修饰
(不同的编译器改名规则不同,但结果都是改变了原有的函数名)。
继承
定义
C++中类的继承特性指的是子类继承父类的成员的一种特性。一旦子类合理的继承了某个父类,就可以直接使用其内部的成员,避免重新添加成员,可减少代码量,增加程序的可读性。
继承的写法如下:Parent类是父类,Children是子类。
class Parent
{
};
class Children : public Parent
{
};
为什么使用继承
class Student
{
public:
int m_age;//共性
int m_score;//个性
void eat() { }//共性
void exam() { }//个性
};
class Worker
{
public:
int m_age;//共性
int m_salary;//个性
void eat() { }//共性
void work() { }//个性
};
那就把共性提取出来设置为父类。让student和worker继承Person,就可以减少代码量,程序的可读性也更高。
class Person
{
public:
int m_age;//共性
void eat() { }//共性
};
class Student : public Person
{
public:
int m_score;//个性
void exam() { }//个性
};
class Worker : public Person
{
public:
int m_salary;//个性
void work() {
cout << m_age << endl;
}//个性
};
子类调用父类的成员
由于Worker继承了Person类,所以可以访问Person中的m_age成员,说白了Person中的成员就是Worker的成员(父类的成员也是子类的成员)
int main(void)
{
Worker worker;
worker.m_age = 10;
worker.work();//打印10
getchar();
return 0;
}
继承的规则
- 如果类A和类B基本上毫不相关,不可以为了让类B的功能更多一点而强行继承类A。不要有那种"不吃白不吃的想法"
- 若在逻辑上B是A的某一个特例,或者说B是A的一种,则类B最好继承类A。
例如男人(Man)是人(Person)的一种,男孩(Boy)又是男人(Man)的一种。那么类Man可以从类Person中派生,类Boy可以从类Man中派生。
class Person //Person是基类
{
public:
int m_age;
...
};
class Man : public Person //Man是Person的派生类
{
public:
int short_hair;
...
};
class Boy : public Man //Boy是Man的派生类
{
public:
int small_height;
...
};
在这里顺便唠叨一句继承时,继承时的内存布局问题。首先Boy上面有父类和所谓的‘爷爷类’,假设每个类里目前存有一个int型的变量。那么Boy类所占内存是多少呢?答案肯定是4*3=12,因为继承其实就是复制粘贴父类的成员到子类中。
那当我创建Boy对象时,内存里的变量是怎么排布的呢(地址)?答案是m_age在Boy对象内存区的顶端,占4个字节,然后是short_hair,最后是small_height。
成员的访问权限
我们知道成员访问权限有三种,分别是:
- public:公共的,任何地方都可以访问(struct默认所有成员都是public)
- protected:受保护的,子类内部和当前类内部可以访问,但是外部不可以访问
- private:私有的,只能在当前类内部访问,子类和外部都不可访问(class默认所有成员都是private)