GOOGLE C++笔记(三)

几个术语翻译

explicit:明确的

implicit:隐含的

trivial:没有意义的

non-trivial:有意义的

1.构造函数

构造函数中应该执行一些打酱油的工作,具体工作应该由

Init函数中处理,但是问题是

当外部NEW出对象来之后,不调用Init直接使用,该对象

需要如何回应,需要负责到哪个地步?

如果要负全部责任的话,

看起来对于不确定状态这种情况,需要使用成员标记指示,

至少可以明确答复失败,不至于出现崩溃等异常情况。

 

下面就一个例子分析一下

1.h

typedef struct 
{
	char test[20];
	int m;
}TEST_S;

class test
{
public:
	test();
	~test();
	int init();
	void printMsg();
private:
	TEST_S* test1;
};


1.cpp

#include "1.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

test::test():test1(NULL)
{

}

test::~test()
{
	if(NULL != test1)
	{
		free(test1);
		test1 = NULL;
	}
}

int test::init()
{
	test1 = (TEST_S*)malloc(sizeof(TEST_S));
	if(NULL == test1)
	{
		printf("Malloc failed\n");
		return -1;
	}

	strcpy(test1->test,"ABC");
	test1->m = 2;
	return 0;
}

void test::printMsg()
{
	printf("Msg:[%s]\n",test1->test);
	printf("Msg:[%d]\n",test1->m);
	return;
}

test.cpp

#include "1.h"

int main()
{
	test testm;
	testm.init();//INIT不调用直接调用函数会有CRASH等异常问题
	testm.printMsg();
}

 

这个例子中 类test提供了init函数给外部,也就是说规定外部必须调用Init,不然的话

接下来的函数调用就不成功,道理是这样,但问题是,不成功的形式,

从上面这个例子看来,不成功就哦了,面子上太过不去了。

如果要完善的话,就需要test内部增加一个运行标记,检查到init没调用就调其他函数

一律回绝,双管齐下的话看起来是一个可以运行的方案。

 

考虑string类

#include <string>
#include <stdio.h>
using namespace std;

int main()
{
	string a("5");
	printf("%s\n",a.c_str());
	return 1;
}

看起来STL和GOOGLE C++是要对着干的态度,还是string类的内部结构隐藏一个惊天秘密?

2.默认构造函数

没有什么可说的,总之要自己定义,不能自动生成

 

3.明确的构造函数

防止单参数构造函数隐式转换

test.cpp

#include <stdio.h>
#include <string>
using namespace std;

class MyClass
{
public:
	explicit MyClass(string name);
	~MyClass();

private:

};

MyClass::MyClass(string name)
{
	printf("con [%s]\n",name.c_str());
}

MyClass::~MyClass()
{
}

int main()
{
	//MyClass A = "ABC";//不加explicit可以编译通过。
	MyClass A("ABC");
}


4.拷贝构造函数与赋值函数

一般来说就是直接关小黑屋(private),可能用的较多的就是STL了。

就用这个DISALLOW_COPY_AND_ASSIGN

 

5.结构体和类

总体来说结构体还是C一样的使用风格,包括内存申请方式也是用malloc为好。(形式上)

如果用new,又想用memset初始化的话,可能会导致非法初始化非POD的严重问题。

扩展阅读。

A plain old data structure (POD) is a data structure that is represented only as passive collections of field values, without using encapsulation or other object-oriented features.

http://zh.wikipedia.org/wiki/POD_(%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1)

 

6.继承

文档强调组合大于继承,只有在子类是基类的基础上才进行继承,例如,飞机是交通工具。

如果有一个类实现了飞行的功能,那么这个类更适合组合(拥有)

在含有虚函数的父类中,定义析构虚函数是必要的(一般来说都是必要的)

子类的虚函数明确标出VIRTURE,没有实际意义,就是要标一下

 

7.多重继承

一般估计用不到

 

8.接口

也不常用

 

9.操作符重载

一般不用,本着科学发展关写个例子意思一下

#include <iostream>
using namespace std;

class test{
public:
test::test():x(0)
{

};

test::~test()
{

};

int x;

}; 

test operator+(const test &test1, const test &test2){ 
	test testm;
	testm.x = test1.x + test2.x;
	return testm; 
} 


int main()
{
	test testn;
	testn.x = 2;

	test testn1;
	testn1.x = 3;

	test testn2 = testn + testn1;
	cout << testn2.x << endl;
	return 1;
}


10.声明次序

在类中使用特定的声明次序:public:在private:之前,成员函数在数据成员(变量)前。

定义次序如下:public:、protected:、private:,如果那一块没有,直接忽略即可。

每一块中,声明次序一般如下:

1) typedefs和enums;

2) 常量;

3) 构造函数;

4) 析构函数;

5) 成员函数,含静态成员函数;

6) 数据成员,含静态数据成员。

宏DISALLOW_COPY_AND_ASSIGN置于private:块之后,作为类的最后部分。参考拷贝构造函数

.cc文件中函数的定义应尽可能和声明次序一致。

 

人民群众喜闻乐见的八股文啊

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值