[C++ 面向对象高级编程]知识点补充1
文章概述
该文章为 侯捷教授的 C++ 面向对象高级编程 课程,主要进行一些知识点补充说明包含一下几个知识点
- static
- class template
- function template
- namespace
作者信息
NEFU 2020级 zsl
ID:fishingrod/鱼竿钓鱼干
Email:851892190@qq.com
欢迎各位引用此博客,引用时在显眼位置放置原文链接和作者基本信息
正文部分
static
首先来看普通的Complex
类的成员函数real()
//省略了一些东西
class complex
{
public:
double real()const{return this->re;}
//double real()const{return re;} this可写可不写,编译器自动补上
private:
double re,im;
}
调用过程
complex c1,c2,c3;
cout << c1.real();
cout << c2.real();
我们的类只有一个成员函数real()
,为了知道谁要使用他就需要this
来表明调用者。我们可以近似的认为上面函数进行了如下操作
complex::real(&c1);
complex::real(&c2);
接下来来看static的情况
class Account {
public:
static double m_rate;
static void set_rate(const double& x) {m_rate = x);
};
double Account::m_rate = 8.0;//必须进行一个初始化的定义
int main(){
Account::set_rate(5.0);//通过class name来调用
Account a;
a.set_rate(7.0);//通过object来调用
return 0;
}
对于static的数据,是每个对象共享一份的。在操作static数据的时候需要注意以下几点。
- static数据需要static函数去操作,static函数只能处理静态的数据
- 通过对象调用static函数不会包含this指针
- static调用方式:通过
object
调用,通过class name
调用 - static数据必须在class外面进行初始化的定义操作
static 在 Singleto单例设计模式中的应用
Singleton设计模式保证类只有一个实例,并且为系统提供一个全局访问点
一般会把构造函数放在private里并创建一个static数据
class A{
public:
static A& getInstance(){return a;};
setup(){
....
}
private:
A();
A(const A& rhs);
static A a;
}
//调用
A::getInstance().setup();
上述代码的缺点是,无论使用调用到这个类都会创建一个static数据,为了优化这一点就,我们在接口函数中创建static数据,这样就只会在调用的时候才创建出来。
//改进版
class A{
public:
static A& getInstance();
setup(){
....
}
private:
A();
A(const A& rhs);
...
}
A& A::getInstance(){
static A a;
return a;
}
class template 类模板
给只有数据不同的类写好几个不同的代码是在太过冗余和浪费时间了,为了处理这种问题,我们可以使用类模板来简化我们的代码。
template类模板会在调用的时候才指定具体的数据类型,使用方式如下
template<typename T>
class complex
{
public:
complex(T re,T im)
:re(r),im(i)
{}
complex& operator +=(const complex&);
T real()const{return re;}
T real()const{return im;}
private:
double im,re;
}
complex<double>c1(2.5,1.5);
complex<int>c2(2,6);
function template
对于函数模板,我们不需要用<>指定具体数据类型,编译器我们帮助我们按照一下步骤自动推导(以上图为例)
- 调用min函数,编译器根据实参推导T
- 推导得到T为stone类
- 调用stone类里的<重载函数
这么做的好处是责任的分离,具体如何比较大小的责任是有具体的数据类型去实现的而不是min函数去实现的
namespace
如果两个不同的库里有同样名称的函数,那么调用的时候编译器就不知道要用哪个了,namespace就是用来处理这种函数名冲突的问题的。
namespace相当于把函数之类的玩意包装起来了,如果你要使用就需要打开这个包装。
using directive
#include<iosteam>
using namespace std;
int main(){
cin<<...;
cout<<...;
}
using declaration
#include<iosteam>
using std::cout;
int main(){
std::cin<<...;
cout<<...;
}
#include<iosteam>
int main(){
std::cin<<...;
std::cout<<...;
}