Effective c++item 19-24

item19:12问帮你高效设计class

1、how should objects of your new type be created and destroyed?
2、how should object initialization differ from object assignment?
3、what does it mean for objects of your new type to be passed by value?
4、what are the restrictions on legal values for your new type?
5、does your new type fit into an inheritance graph?

Virtual function(like destroy function),

6、what kind of type conversions are allowed for your new type?

实现一些类型转换的函数;如果只允许显式的转换,则需要添加explicit限定符禁止隐式转换。

7、what operators and functions make sense for the new type?

What functions should be a member function

8、what standard functions should be disallowed?

for example, copy and move is prohibited in std::mutex

9、who should have access to the members of your new type?

public? private? or protected?

10、what is the “undeclared interface” of your new type?
11、how general is your new type?

maybe you should use template class

12、is a new type really what you need?

maybe just need some non-member method

item20:const引用传递优于按值传递

1、效率高
class A{};
class B:public A{};

bool ischeck(A a);
A a;
bool check = ischeck(a);

如果采用值传递,ischeck函数内将再次调用构造函数,总共将调用至少4⃣️次构造函数。
建议使用引用传递,为了防止更改参数值,建议加上const

Bool ischeck(const A& a);
2、防止多态未调用
class A{
public:
	virtual void display() const;
};

class B:public A{
public:
	virtual void display() const;
};

void print(A a){		// incorrect!! This will construct a class of A
	a.display();		// parameter don’t have function display
}

void print(const A& a){
	a.display();			// correct!!
}

int main(){
	B b;
	print(b);
}
  • prefer pass-by-reference-to-const over pass-by-value. It’s typically more efficient and it avoids the slicing problem.
  • the rule doesn’t apply to built-in types and STL iterator and function object types. for them, pass-by-value is usually appropriate.

item21:不要错误的返回对象的引用

1、可能会返回为定义地址或造成内存泄漏
// one
const A& operator*(const A& lhs, const A& rhs){
	A a(lhs.x * rhs.x, lhs.y * rhs.y);
	return a;			// a为局部变量,返回了一个无效地址
}

// two
const A& operator*(A& lhs, A& rhs){
	A* a = new A(lhs.x * rhs.x, lhs.y * rhs.y);
	return *a;		// 可能会造成内存泄漏
}

A a, b, c, d;
a = b * c * d;		// aka a = (b * c) * d, (b*c)的结果没有被保存下来
静态变量
const A& operator*(A& lhs, A& rhs){
	static A a;		// static object to which a reference will be returned
	a = ...;		// multiply lhs and put the product inside result
	return a;		
}

A a, b, c, d;
if((a * b) == (c * d))	// a * b和c * d的返回值都是静态变量的地址,故等式恒成立
	....	
返回索引值的引用以便用户修改

item22:将成员变量声明为private

1、使成员变量有更精细的方位控制

对外部可以进行操作的变量提供set和get;对只读的变量提供get等

2、有利于封装

当需求更改时只需要更改操作变量的函数

item23:非成员非友元函数替换成员函数

// Web.h
namespace WebBrowser{
	class Web{
	public:
		void clearCache();
		void clearHistory();
		void removeCookies();
	};
	void clearBrowser(Web& w){	// 只能访问这三个函数,封装性好
		w.clearCache();
		w.clearHistory();
		w.removeCookies();
	}
}

// Webbooks.h					// 在不同文件中包含相同命名空间
namespace WebBrowser{			//有不同的需求包含不同头文件就行,如STL
...
}

// Webcookies.h
namespace WebBrowser{
...
}

item24:当所有参数都需要进行类型转换时,将函数定义为非成员函数

A a(1, 8);
A b(1, 2);
A c = a * b;  		// ok
c = c * a;			// ok
c = a * 2;			// c = a * 2 = a.operator*(2) = a.operator*(A temp(2))

// error!!!
c = 2 * a;			// c = 2 * a = 2.operator*(a); or c = operator*(2, a); 

为了避免以上第四种情况,将operator*定义为非成员函数:

#include <iostream>
using namespace std;
class A{
public:
 A(int q1 = 1, int q2 = 3):x(q1), y(q2){}
 int x, y;
};
const A operator*(const A& lhs, const A& rhs){
    return {lhs.x * rhs.x, lhs.y * rhs.y};
}
    
int main(){
        A a(1, 2);
        A b;
        b = a * 2;
        cout << b.x << b.y << endl;		// 2  6
        c = 2 * a;
        cout << c.x << c.y << endl; 	// 2 6
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值