侯捷c++面向对象 笔记(三)

static

this

数据或函数之前添加,成为静态数据或静态函数

成员函数隐藏参数this,可以直接在成员函数中调用,可以在函数体中出现

静态函数没有this这个隐藏参数,如果要处理数据的话只能处理静态数据

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Account {
public:
static double m_rate;//只声明
static void set_rate(const double & x) {
m_rate = x;
}
};
double Account::m_rate = 8.0;//定义,class外设初值

int main() {
Account::set_rate(5.0);//通过类名直接调用

Account a;
a.set_rate(7.0);//通过对象调用
return 0;
}

c++中单例的写法

private区创建一个静态对象,全局只有一份
将这个类的构造方法放在private区,这样外界无法调用构造函数创建该对象
在public区创建一个静态函数,通过这个函数获取创建的静态对象,达到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A{
public:
static A& getInstance(return a;);//静态函数,获取全局唯一的静态对象
setup() {} //其他普通函数

private:
A();//构造函数放在private区,外界无法创建多个对象
A(const A& rhs);
static A a; //全局仅存在一份的静态对象
};

//使用
A::getInstance()//获取a
A::getInstance().setup()//通过单例a调用其他函数

如果外界没有用到a,它也存在,有点浪费,改进:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A{
public:
static A& getInstance();//静态函数,获取全局唯一的静态对象
setup() {} //其他普通函数

private:
A();//构造函数放在private区,外界无法创建多个对象
A(const A& rhs);
};

//将全局的静态对象放在获取单例的函数中,只有当有被调用时,a才会被创建,函数调用完成后,a还在
A& A::getInstance() {
static A a;
return a;
}

对比一下oc的严格单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Singleton.h
@interface Singleton : NSObject
@property(nonatomic,strong) NSString *name;
+(Singleton*)defaultManager;
@end


Singleton.m
@implementation Singleton
//单例类的静态实例对象,因对象需要唯一性,故只能是static类型
static Singleton *defaultManager = nil;

/**单例模式对外的唯一接口,用到的dispatch_once函数在一个应用程序内只会执行一次,且dispatch_once能确保线程安全
*/
+(Singleton*)defaultManager
{
static dispatch_once_t token;
dispatch_once(&token, ^{
if(defaultManager == nil)
{
defaultManager = [[self alloc] init];
}
});
return defaultManager;
}

/**覆盖该方法主要确保当用户通过[[Singleton alloc] init]创建对象时对象的唯一性,alloc方法会调用该方法,只不过zone参数默认为nil,因该类覆盖了allocWithZone方法,所以只能通过其父类分配内存,即[super allocWithZone:zone]
*/
+(id)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t token;
dispatch_once(&token, ^{
if(defaultManager == nil)
{
defaultManager = [super allocWithZone:zone];
}
});
return defaultManager;
}
//自定义初始化方法,本例中只有name这一属性
- (instancetype)init
{
self = [super init];
if(self)
{
self.name = @"Singleton";
}
return self;
}

//覆盖该方法主要确保当用户通过copy方法产生对象时对象的唯一性
- (id)copy
{
return self;
}

//覆盖该方法主要确保当用户通过mutableCopy方法产生对象时对象的唯一性
- (id)mutableCopy
{
return self;
}
//自定义描述信息,用于log详细打印
- (NSString *)description
{
return [NSString stringWithFormat:@"memeory address:%p,property name:%@",self,self.name];
}

类模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template<typename T>
class complex {
public:
complex (T r = 0, T i = 0)
: re (r), im (i)
{}
complex& operator += (const complex&);
T real () const { return re;}
T imag () const { return im;}
private:
T re, im;
friend complex& __doapl (complex*, const complex&);
};

//在使用complex类时,需要传入你想用的类型,编译器将上面的T全部替换为传入类型
{
complex<double> c1(2.1, 2.2);
complex<int> c2(1,2);
}

模板的使用会造成代码的膨胀,但这是必须的

函数模板

参数类型推导argument deduction

1
2
3
4
5
6
7
template<class T>
inline const T& min(const T& a, const T& b) {
return b < a ? b : a;
}
//使用时,函数模板不用说明类型,编译器会做参数类型推导
stone r1(2,3), r2(3,4), r3;
r3 = min(r1, r2);

注意stone类中的运算符重载

这样的设计合理吗?
不管什么类,比大小都是”<“,但是具体到每个类,如何比大小只有每个类自己知道,所以应该由每个类自己去决定(实现),而不是比大小的人(调用者)决定

namespace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
namespace std {
//所有的东西都被包装在名字空间(命名空间)内
}

//using directive
#include <iostream>
using namespace std;
int main() {
cin << ...;
return 0;
}

//using declaration
#include <iostream>
using std:cout;
int main() {
std::cin << ...;
cout << ...;
return 0;
}

//啥都不用
#include <iostream>
int main() {
std::cin << ...;
std::cout << ...;
return 0;
}

using directive:using命令,全部打开
using declaration:using声明,部分打开

其他

  • operator type() const; 转换函数
  • explicit complex(…):initialization list{} 特殊的构造函数
  • pointer-like obj
  • function-like obj
  • namespace
  • template specialization 模板特化
  • standard library
  • variadic template(since C++11)
  • move ctor(since C++11)
  • rvalue reference(since C++11)
  • auto(since C++11)
  • lambda(since C++11)
  • range-base for loop(since C++11)
  • unordered containers(since C++11)
文章作者: ゴウサク
文章链接: http://dapaner.top/2022/04/12/侯捷c-面向对象-笔记(三)/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Corner&Coder
微信赞赏码
支付宝赞赏码