(C++)静态函数和非静态函数

static

class Account {
public:
	static double m_rate;
	static void set_rate(const double& x) { m_rate = x; }
private:
}
double Account::m_rate = 8.0;//静态变量必须在类外定义,可以不设初值,但是必须分配内存

int main() {
	Account::set_rate(5.0);
	Account a;
	a.set_rate(7.0);
}

知识小记:

  1. 静态函数和非静态函数一样只有一份,但是静态函数没有this指针,所以只能处理静态变量
  2. 静态变量必须在类外定义,可以不设初值,但是必须分配内存
  3. 静态函数可以通过object来调用,也可以通过class name来调用

单例模式(Singleton)

class A {
public:
	static A& getInstance(){ return a; }
	setup() {...}
private:
	A();
	A(const A& ths);
	static A a;
	...
}

不足之处:强制性地生成静态对象。 问题:

  1. class中有相同class的成员变量的情况下,内存模型是什么样的?
    如果是自己类的成员,必须是指针,不过如果有static作修饰的时候可以忽略这个限制。
  2. getInstance(return a;);是什么意思? 貌似是语法错误。
class A {
public:
	static A& getInstance();
	setup() {...}
private:
	A();
	A(const A& rhs);
	...
}

A& A::getInstance()
{
	static A a;
	return a;
}

知识点:

  1. 构造函数是private属性
  2. 调用getInstance()的时候才会创建静态对象,函数结束之后,静态变量仍然存在
  3. getInstance()返回的是一个静态的引用

cout

class _IO_ostream_withassign : public ostream {
	...
};
extern _IO_ostream_withassign cout;

ostream重载了很多次操作符<<

class template

template<typename T>//注意关键字是typename
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(conplex*, const complex&);
}

int main()
{
	complex<double> c1(2.5,1.5);
	complex<int> c2(2,6);
	return 0;
}

注意:typename T,使用时要明确指出T是哪个类型

function template

template <class T>//注意关键字是class
inline const T& min(const T& a, const T& b)
{
	return b < a ? b : a;//<需要在类中重载
}

注意:class T ,使用时不需要指出T是哪一个类型

模板还有很多细节,需要继续自己去学习!

namespace

namespace std
{
	...
}

三种用法:

  1. using directive: using namespace std
  2. using declaration: using std::cout
  3. 调用时才说明:std::cin

更多细节

  • operator type() const;
  • explicit complex(…): initialization list{}
  • pointer-like object
  • function-like object
  • namespace
  • template spcialization
  • standard specialization
  • Standard Library
  • variadic template(since C++11)
  • move ctor(since C++11)
  • Rvalue reference(since C++11)
  • auto (since C++11)
  • lamdba(since C++11)
  • range-base for loop(since C++11)
  • unordered containers(since C++)

composition(组合)

composition表示has-a的关系。

template <class T>
class queue {
protected:
	deque<T> c; //底层容器
public:
	//以下完全利用deque的操作函数完成
	bool empty() const { return c.empty();}
	size_type size() const {return c.size();}
	reference front() {return c.front();}
	reference back() {return c.back();}
	//
	void push(const value_type& x) {c.push_back(x);}
	void pop() {c.pop_front();}


}

queue中所有的功能都可以通过deque来实现,这是一种叫作Adapter的设计模式,相当于对deque进行改造。这里的deque表示两端都可以进出的队列。 composition关系下,容器和组件的生命周期是一起的。

Composition下的构造和析构

构造是由内而外的

Container::Container(...) : Component() { ... };

Container的构造函数首先会调用Componentdefault构造函数,然后再执行自己的。component内部也许会有很多个构造函数,编译器不知道要调用哪一个构造函数,所以只能选择默认的,如果需要调用其他的构造函数,则需要自己去手动写。

析构是由外而内的

Container::~Container(...) {... ~Component() };

Container的析构函数首先执行自己,然后才调用Component的析构函数。

Delegation(委托)

就是用通过指针或者引用实现的composition。所以也叫Composition by referencecppby reference包括指针和引用。

//file String.hpp
class StringRep;//前向声明
class String {
public:
	String();
	String(const char* s);
	String(const String& s);
	String& operator=(const String& s);
	~String();
private:
	StringRep* rep;//pimpl
}

委托关系下,容器和组件的生命是不一致的。
这种写法被称之为point to implementation。也就是说我有一个指针去指向所有实现我的功能的那一个类。这个手法又叫做编译防火墙

Inheritance(继承)

继承表示is a的关系。

struct _List_node_base
{
	_List_node_base* _M_next;
	_List_node_base* _M_prev;
};

template<typename _Tp>
struct _List_node : public _List_node_base
{
	_Tp _M_data;
}

父类的数据可以被完整地继承下来。但这并不是继承最有价值的部分,跟虚函数搭配才是最有价值的部分。
从内存的角度来看,子类的对象有父类的成分在里头。结合composition我们可以得到类似的结论。如下。

  1. 构造由内而外
    首先是Base的构造函数然后是derived的构造函数。
  2. 析构由外而内
    首先调用derived的析构函数然后是base的析构函数。 注意事项: base classdtor必须是virtual的,否则就会出现undefined behavior
打赏还是要有的,万一有人打赏呢!