C++ Primer : 关键字static可以说是检验一个C++程序员基本功的不二法门,挑马桶这件事永远只有进行时

前提

C++ is a statically typed language, which means that types are checked at compile time. C++是一门静态语言,所以才有类型的check,所以需要考虑是否为static静态类型

单词pimer的释义

这纯属本人捏造的趣事。prime通常指一个人一生中最活跃,最黄金的阶段,且Prime often means "main."

作为程序员对main函数,再熟悉不过,所以《c++ primer》就是一本把C++从main函数出发以后的几乎所有细枝末节给你铺开

讲的明明白白的一本书,它也可能是你一生中最活跃,最黄金的时候与它常打交道的一本书了。

static

有一个局部变量,它的生存期在对函数的调用中持续,这是很有用的。 如果局部静态没有显式初始化式,则对其进行值初始化,这意味着将内置类型的局部静态初始化为零。

cpp 复制代码
size_t count_calls()
{
static size_t ctr = 0; // value will persist across calls
return ++ctr;
}
int main()
{
for (size_t i = 0; i != 10; ++i)
cout << count_calls() << endl;
return 0;
}

类有时需要与类关联的成员,而不是与类类型的单个对象关联的成员。

cpp 复制代码
class Account {
public:
	void calculate() { amount += amount * interestRate; }
	static double rate() { return interestRate; }
	static void rate(double);
private:
	std::string owner;
	double amount;
	static double interestRate;
	static double initRate();
};

The static members of a class exist outside any object.


We can access a static member directly through the scope operator:

cpp 复制代码
	double r;
	r = Account::rate(); // access a static member using the scope operator

即使静态成员不是其类的对象的一部分,也可以使用类类型的对象、引用或指针来访问静态成员:

cpp 复制代码
	Account ac1;
	Account& ac3 = ac1;
	Account* ac2 = &ac1;
	// equivalent ways to call the static member rate function
	r = ac1.rate(); // through an Account object or reference
	r = ac3.rate(); // through an Account  reference
	r = ac2->rate(); // through a pointer to an Account object

成员函数可以直接使用静态成员,不需要作用域操作符:

cpp 复制代码
class Account {
public:
	void calculate() { amount += amount * interestRate; }
private:
	double amount;
	static double interestRate;
	// remaining members as before
};

初始化静态成员变量

cpp 复制代码
// define and initialize a static class member
double Account::interestRate = initRate();

static const类型的使用

cpp 复制代码
class Account {
public:
	static double rate() { return interestRate; }
	static void rate(double);
private:
	static constexpr int period = 30;// period is a constant expression
	double daily_tbl[period];
	static double interestRate;
};

如果在类内部提供了初始化式,则成员的定义不能指定初始值:

cpp 复制代码
	// definition of a static member with no initializer
	constexpr int Account::period; // initializer provided in the class definition

静态数据成员可以具有不完整类型

非静态数据成员只能声明为指向其类对象的指针或引用:

cpp 复制代码
class Bar {
public:
	// ...
private:
	static Bar mem1; // ok: static member can have incomplete type
	Bar* mem2; // ok: pointer member can have incomplete type
	Bar mem3; // error: data members must have complete type
};

静态成员与普通成员的另一个区别是,可以将静态成员用作默认实参

cpp 复制代码
class Screen {
public:
	// bkground refers to the static member
	// declared later in the class definition
	Screen& clear(char = bkground);
private:
	static const char bkground;
};

继承树中的static成员,整个层次结构只定义了一个这样的成员。

cpp 复制代码
class Base {
public:
	static void statmem();
};
class Derived : public Base {
	void f(const Derived&);
};

静态成员服从普通的访问控制。如果成员在基类中是私有的,则派生类无法访问它。假设成员是可访问的,则可以通过基类或派生类使用静态成员:

cpp 复制代码
void Derived::f(const Derived& derived_obj)
{
	Base::statmem(); // ok: Base defines statmem
	Derived::statmem(); // ok: Derived inherits statmem
	// ok: derived objects can be used to access static from base
	derived_obj.statmem(); // accessed through a Derived object
	statmem(); // accessed through this object
}

类模板的static成员

cpp 复制代码
template <typename T> class Foo {
public:
	static std::size_t count() { return ctr; }
	// other interface members
private:
	static std::size_t ctr;
	// other implementation members
};

模板类静态实例化

cpp 复制代码
// instantiates static members Foo<string>::ctr and Foo<string>::count
Foo<string> fs;
// all three objects share the same Foo<int>::ctr and Foo<int>::count members
Foo<int> fi, fi2, fi3;

模板类静态初始化

cpp 复制代码
template <typename T>
size_t Foo<T>::ctr = 0; // define and initialize ctr

模板类静态成员的使用

cpp 复制代码
Foo<int> fi; // instantiates Foo<int> class
// and the static data member ctr
auto ct = Foo<int>::count(); // instantiates Foo<int>::count
ct = fi.count(); // uses Foo<int>::count
ct = Foo::count(); // error: which template instantiation?

嵌套类静态成员定义

cpp 复制代码
// defines an int static member of QueryResult
// which is a class nested inside TextQuery
int TextQuery::QueryResult::static_mem = 1024;

static_assert

水平不够,未来有时间来补上

static_cast

  1. 当将较大的算术类型赋值给较小的类型时,static_cast通常很有用。强制类型转换告知程序的读者和编译器,我们知道并且不关心潜在的精度损失。将较大的算术类型赋值给较小的类型时,编译器通常会生成警告。当我们执行显式强制转换时,警告消息将被关闭。
cpp 复制代码
// cast used to force floating-point division
double slope = static_cast<double>(j) / i;
  1. 对于执行编译器不会自动生成的转换,static_cast也很有用。例如,可以使用static_cast来检索存储在void*指针.
cpp 复制代码
void* p = &d; // ok: address of any nonconst object can be stored in a void*
// ok: converts void* back to the original pointer type
double *dp = static_cast<double*>(p);
  1. static_cast更深的运用,路还远,任重而道远呐

C++挑马桶基本功

  1. for循环的简单遍历,不在手写低效for循环。
cpp 复制代码
// print words of the given size or longer, each one followed by a space
for_each(wc, words.end(),
[](const string &s){cout << s << " ";});
cout << endl;
  1. 自从C++11有了智能指针,C++里一切稍微占据大量内存的数据都应该用智能指针,因为性能的缘故
cpp 复制代码
// C++万物可指针
class HugeData {
public:
	HugeData() {
	}
	void init() {
		data_ = new std::list<HugeData*>{};
	}
	void work() {
	}
private:
	static std::list<HugeData*>* data_;
};

// 但是智能指针岂不更香
class HugeData {
public:
	HugeData() {}
	void init() {
		data_ = std::make_shared<std::list<std::shared_ptr<HugeData>> >();
	}
	void work() {}
private:
	static std::shared_ptr < std::list<std::shared_ptr<HugeData>> > data_;
};
相关推荐
程序猿小D4 分钟前
第二百六十九节 JPA教程 - JPA查询OrderBy两个属性示例
java·开发语言·数据库·windows·jpa
阿华的代码王国12 分钟前
【JavaEE】——文件IO的应用
开发语言·python
satan–017 分钟前
R语言的下载、安装及环境配置(Rstudio&VSCode)
开发语言·windows·vscode·r语言
电饭叔1 小时前
《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
开发语言·python
Eternal-Student1 小时前
everyday_question dq20240731
开发语言·arm开发·php
卑微求AC1 小时前
(C语言贪吃蛇)11.贪吃蛇方向移动和刷新界面一起实现面临的问题
c语言·开发语言
程序猿小D1 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
Yvemil71 小时前
RabbitMQ 入门到精通指南
开发语言·后端·ruby
潘多编程2 小时前
Java中的状态机实现:使用Spring State Machine管理复杂状态流转
java·开发语言·spring
QuantumStack2 小时前
【C++ 真题】B2037 奇偶数判断
数据结构·c++·算法