Key Words | 关键字👀
约 1444 个字 278 行代码 预计阅读时间 8 分钟
Const
👀
- declares a variable to have a constant value
- Constants are variables
- Observe scoping rules
- Declared with “const” type modifier
- A const in C++ defaults to internal linkage
- the compiler tries to avoid creating storage for a const – holds the value in its symbol table
- extern forces storage to be allocated
- Compile time constants
const int bufsize = 1024;
- value must be initialized
- unless you make an explict extern declaration:
extern const int bufsize;
- Compiler won’t let you change it
- Compile time constants are entries in compiler symbol table, not really variables
-
Run-time constants
- const value can be expolited
-
Aggregates
- It’s possible to use const for aggregates, but storage will allocated. In these situations, const means “read-only”. However, the value cannot be used at compile time because the compiler is not required to know the contents of the storage at compile time.
-
Pointers and const – a pointer may be const
char * const p = "abc";
–p
is a const pointer to char*q = 'c';
– okq++;
– error
const char * p = "abc";
–*p
is a const char*p = 'c';
– error- 指针可变(指向别人),指针所指向的内存也可变,不能做的是通过这个指针改变指向内存的值
char const * p = "abc";
– same as aboveconst char * p = "abc";
-
String Literals
char *s = "Hello";
s
is a pointer initialized to point to a string constant- This is actually a
const char *s
, but compiler accepts it - Don’t try to change the character (it is undefined behavior)
- If you want to change the string, put it in an array –
char s[] = "Hello";
-
const object
const Currency price(3, 50);
- 此时,编译器会制止修改
price
中 public 成员变量以及调用price
中修改成员变量函数的操作
编译器怎么知道调用了会修改成员变量的函数 (非 inline)
- 引入新机制 - declare member functions as const
int Date::set_day(int d) { // ... error check d here day = d; // ok, non-const so can modify } int Date::get_day() const { day ++; // ERROR modifies data member set_day(1); // ERROR calls non-const function return day; // ok, doesn't modify anything }
- 此时若 Date 类的对象为 const,那么该对象不能调用除 const、static 之外的类的成员函数,否则会报错
- 成员函数声明尾部带有 const,那么只能调用带有 const 的成员函数且无法修改成员函数等
- Const member function usage
- Repeat the
const
keyword in the function declaration and definition if the function is defined outside the class definition int get_day() const;
&int Date::get_day() const { ... }
- Repeat the
- Function members that do not modify the object should be declared const
- const member functions are safe for const objects
const member functions can be overloaded
code
int get_day() const;
&int get_day();
const
is part of the function signature- As the code showed right, when coming across member functions with same name and arguments,
const
object will callconst
member function, non-const
object will call non-const
member function get_day()
&get_day() const
看起来没有参数,实际有隐藏参数int get_day()
->int get_day(Date *this)
int get_day() const
->int get_day(const Date *this)
- 编译器就可通过
this
来判断
-
Constant in class
const
object’s member variable (non-const) must be initialized in constructor or initializer list (即你认为这个对象不可改变,但这个对象里面的变量起码要有个值)- if the member variable is a const
- must be initialized in the initializer list
- or directly initialized in the class definition (for c++11 and later) ->
const int a = 1;
static
👀
Static in C++
- Two basic meanings
- Static storage duration
- allocated once at a fixed address
- Visibility of a name
- internal linkage
- Don’t use except inside functions and classes
- Static storage duration
- 只有进入 f 函数时,才会调用 A 的构造函数,且只调用一次 (static 的存储地址不在栈中而在全局中)
-
Static applied to objects
- Constructor occurs when definition is encountered
- Constructor is called only once
- The constructor arguments must be satisfied
- Destruction take place on exit from the program
- Compiler assures LIFO order of destruction
Conditional construction
Tip
- avoid non-local static dependencies
- Put static object definitions in a single file in correct order
- Constructor occurs when definition is encountered
Static members👀
Can we apply static to members
- Static means “Hidden” & “Persistent”
- Hidden: A static member is a member (obey usual access rules)
- Persistent: Independent of instances
- 静态成员变量类似静态本地变量,是全局变量,访问限制于类中
- 静态成员函数是只能访问静态成员变量的函数,不能访问非静态成员变量
- Static member variables
- Global to all class member functions
- Initialized once, at file scope
- provide a place for this variable and init it in
.cpp
- No
static
in.cpp
Example
#include "StatMem.h"
#include <iostream>
using namespace std;
int StatMem::m_h; // 一个静态的成员变量一定要在对应的 cpp 文件中放一个全局的定义
int main()
{
StatMem sm1, sm2;
int i = 0;
cout << sizeof(i) << endl;
cout << "i=" << i << endl;
sm1.setHeight(10);
cout << sm2.getHeight() << endl;
sm1.setWeight(20);
cout << sm2.getWeight() << endl;
cout << &sm1 << '\t' << &(sm1.m_h) << '\t' << &(sm1.m_w) << endl;
cout << &sm2 << '\t' << &(sm2.m_h) << '\t' << &(sm2.m_w) << endl;
cout << sizeof(StatMem) << endl;
return 0;
}
m_h
is a static member variable, it is global to all class member functions | 存放在全局而不是栈中,且sm1
和sm2
都指向同一个m_h
StatMem
中只有一个int
的大小,地址相差 8 是因为 64 位的机器一个 word 占 8 个字节
- Static member functions
- Global to all class member functions
- No
this
pointer - Can access only static member variables
- No
static
in.cpp
- Can’t be dynamicallly overriden
Namespace👀
Namespace
- Expresses a logical grouping of classes, functions, variables, etc.
- A namespace is a scope just like a class
- Preferred when only name encapsulation is needed
大括号后不需要有分号
-
Defining namespaces | 命名空间的定义
- Place namespace definition in include file:
-
Defining namespace functions | 命名空间函数的定义
- Use normal scoping to implement functions in namespaces
-
Using names from a namespace | 使用命名空间中的名字
- Use scope resolution to qualify names from a namespace
- Can be tedious and distracting
-
Using-Declarations | 使用声明
- Introduces a local synonym for name
- States in one place where a name comes from
- Eliminates redundant scope qualification
-
Using-Directives | 使用指令
- Make all names from a namespace available
- Can be used as a notational convenience
More details👀
-
Ambiguities | 歧义
- Using-directives may create potential ambiguities
- Using-directives only make the names available
- Ambiguities arise only when you make calls.
- Use scope resolution to resolve
-
Namespace aliases | 命名空间别名
-
Namespace composition | 命名空间组合
- Compose new namespaces using names from other ones
- Using-declarations can resolve potential clashes
- Explicitly defined functions take precedence
#include <iostream> namespace first { void x(); void y(); } namespace second { void y(); void z(); } void first::x() { std::cout << "first::x()" << std::endl; } void first::y() { std::cout << "first::y()" << std::endl; } void second::y() { std::cout << "second::y()" << std::endl; } void second::z() { std::cout << "second::z()" << std::endl; } namespace mine { using namespace first; using namespace second; using first::y; // resolve clash to first::y() void mystuff() { x(); y(); z(); } } int main() { using namespace mine; mystuff(); }
extern “C”
extern "C"
tells the compiler to use C linkage- 旧版的 C 语言中没有命名空间,直接
#include "oldc.h"
会导致命名冲突 (链接成汇编,函数名不会加_
) - 对于新的 C++ 语言,
#include "newc.h"
会自动加上_
,所以不会有命名冲突 - 故在使用旧版 C 语言的头文件时,需要加上
extern "C"
,告诉编译器使用 C 语言的链接方式
-
Namespace selection | 命名空间选择
- Compose namespaces by selecting a few features from other namespaces
- Choose only the names you want rather than all
- Changes to “orig” declaration become reflected in “mine”
-
Namespaces are open | 命名空间是开放的
- Multiple namespace declarations add to the same namespace
Namespace can be distributed across multiple files
- Multiple namespace declarations add to the same namespace
本文总阅读量:
次