Classes encapsulate—combine into a single logical unit— the data and methods that act on them
BankAccount myAccount; //declare a variable of type BankAccount
myAccount.initAccount(); //call initAccount() on myAccount
myAccount.deposit(42.50); //call deposit(42.50) on myAccount
//const T * const this
class Point {
private:
int x;
int y;
public:
void setX(int new_x) {
x = new_x;
}
void setY(int new_y) {
y = new_y;
}
int getX() const {
return x;
}
int getY() const {
return y;
}
};
can invoke a const method upon a const object but cannot invoke a non-const method upon a const object
void someMethod(const Point * p) {
int x = p->getX(); //legal: getX() is const
p->setX(42); //illegal: setX is not const
//but *p is const!
}
1.4 Plain Old Data
plain old data (POD) classes -> all POD types have direct C analogs—they are just sequences of fields in memory that you could copy around freely
Exception: if you declare functions (a.k.a. methods) inside of a class or struct, they do not make the type non-POD (unless they are virtual functions)
the code for functions is just placed with the rest of the code in memory and just takes the extra this parameter to tell which object it is currently operating on 代码实际不在object里
以下两个代码块相同
class MyClass {
public:
int x;
int y;
int getSum() const { return x + y; }
};
typedef struct {
int x;
int y;
} MyClass;
int getSum (const MyClass * const this) {
return this->x + this->y;
}
can allocate POD types with malloc, copy with memcpy, and deallocate them with free.
With any non- POD type, you cannot work on the “raw” memory directly in a safe way, whether it is allocating, copying, or deallocating that memory. Instead, you have to use the C++ operators that know how to work with non- POD types properly.
1.5 Static Members
static means that there is one “box” shared by all instances of the BankAccount class, not one box per instance
实际上在class内没有box,在外面有box,且要在class外单独定义
class BankAccount {
private:
static unsigned long nextAccountNumber;
unsigned long accoutNumber;
double balance;
public:
unsigned long getAccountNumber() const {
return accoutNumber;
}
void deposit(double amount) {
balance += amount;
}
double withdraw(double desiredAmount) {
if (desiredAmount <= balance) {
balance -= desiredAmount;
return desiredAmount;
}
else {
double actualAmount = balance;
balance = 0;
return actualAmount;
}
}
double getBalance() const {
return balance;
}
void initAccount() {
accoutNumber = nextAccountNumber;
nextAccountNumber++;
balance = 0; //we will see a better way to do this later
}
};
unsigned long BankAccount::nextAccountNumber = 0;//:: scope resolution operator 作用域解析 在main运行前运行
Static methods in a class cannot access non-static members of the class because unlike non-static methods, they do not have a this pointer passed to them—they operate on no particular object.
methods of an inner class do not have direct access to non- static members of the outer class. methods inside the inner class have a this pointer that points at the object that is an instance of that inner class (e.g., it is a pointer to a Transaction), and does not have a pointer to the outer-class instance (e.g., BankAccount) that created them (in fact, there might not be one). If we want to let the inner class reference the outer class, we can do so easily by having a field in the inner class that is a pointer to the outer class type and initializing it to point at the appropriate outer-class instance.
1.7 The Basics of Good OO Design
Classes are nouns. Methods are verbs.
Keep classes small and to their purpose.
Be as general as you can be, but no more.
Avoid “Manager” classes.
2 References
reference不能是NULL,一开始就要初始化,自动解引用,不能被更改
错误: int && x int&* x
正确:int *&x a reference to a pointer
指针可以进行数学运算,但reference不能
int f(int & x, int y) {
int z = x + y;
x = z;
return z - 2;
}
int g(int x) {
int z = f (x, 3);
int & r = z;
r++;
return z * x;
}
int f(int * const x, int y) {
int z = (*x) + y;
(*x) = z;
return z - 2;
}
int g(int x) {
int z = f (&x, 3);
int * const r = &z;
(*r)++;
return z * x;
}
以上两者等价,可以互相转换(大多数情况 -> 当一个const reference初始化时被赋的不是lvalue时不成立 -> const int & x = 3 此外,pointer和reference数据类型不同)
Declaration: T & --> T * const
Initialization: 右边z --> &z ; 调用function的形参–> 加*
Uses: 解引用–> 前面加*
a call to a function that returns a (non-const) reference may be used as the left side of an assignment statement
3 Namespaces 命名空间
namespace dataAnalysis {
class DataPoint { ... };
class DataSet { ... };
DataSet combineDataSets(DataSet * array, int n);
}
两种方法 reference a name declared inside of a namespace
:: --> fully qualified name --> std::vector
using namespace std; 然后正常使用vector类即可 --> open the entire namespace, and could just write vector to refer to std::vector using std::vector; --> bring only the name vector from the std namespace into scope --> preferred
using可同时打开多个namespace,但出现同名需要指出想要的函数
4 Function Overloading 函数重载
int f(int x, double d) {...}
double f(double d, int x) {...}
void f(int y) {...}
int f(double d) {...}
double f(void) {}
int f(int * p) {}
int f(const int * p) {}
only overload functions when they perform the same task but on different types
only overload functions in such a way that understanding what the “best choice” is for a particular call is straightforward
4.1 Name Mangling 名称修改
name mangling—adjusting the function names to encode the parameter type information, as well as what class and namespace the function resides inside of—so that each name is unique
mix C and C++ code, the C++ compiler must be explicitly informed of functions that were compiled with a C compiler by declaring them extern “C”
class Point {
private:
int x;
int y;
public:
Point operator+(const Point & rhs) const {
Point ans;
ans.x = x + rhs.x;
ans.y = y + rhs.y;
return ans;
}
};
the first (left) operand is the this object
pass a const reference rather than the value so that avoid copying the entire object as we pass the parameter (which is generally the correct way to pass the right-operand argument of an overloaded operator)
Matrix operator+(const Matrix & rhs) {//2个矩阵相加
//implementation goes here
}
add another Matrix to the current one, updating the current matrix with the sum
in the case of operators that modify the object they are inside of, such as +=, they return a reference to that object
their return type is a reference to the their own class type, and they return *this
when returning *this, a reference (the return value) is being initialized, thus the address is implicitly taken; that is, the pointer is &*this, which is just this
MatrixRow & operator[](int index) {
//code here
}
const MatrixRow & operator[](int index) const {
//implementation here
}
get a const (i.e., read-only) row from a const Matrix
6 Other Aspects of Switching to C++
6.1 Compilation
G++ -stg=gnu++98
6.2 bool type
bool a = true;
bool b = false;
C++ will still respect C-style use of an integer as meaning false if the integer is 0 and true otherwise; however, you should generally use bool for the type of parameters and variables that represent a boolean value
6.3 void Pointers
In C, we can assign any pointer type to a void pointer and assign a void pointer to any pointer type without a cast
C++ removes this flexibility and requires an explicit cast
6.4 Standard Headers
#include <vector>
cstdlib for stdlib.h and cstdio for stdio.h
they are placed in the std namespace (so cstdio would provide std::printf) 它们不在global scope里,属于别的namespace
//.cpp file
#include "bank.h"
void BankAccount::deposit(double amount) {
balance += amount;
}
double BankAccount::withdraw(double desiredAmount) {
if (desiredAmount <= balance) {
balance -= desiredAmount;
return desiredAmount;
}
else {
double actualAmount = balance;
balance = 0;
return actualAmount;
}
}
double BankAccount::getBalance() const {
return balance;
}
void BankAccount::initAccount() {
balance = 0; we will see a better way to do this later
}
6.6 Default Values
arguments that are omitted must be the rightmost arguments of the call
int f(int x, int y = 3, int z = 4, bool b = false);
f(9); //x=9,y=3,z=4,b=false
f(9, 8); //x=9,y=8,z=4,b=false
f(9, 8, 7); //x=9,y=8,z=7,b=false
f(9,8,7,true); //x=9,y=8,z=7,b=true
use default parameters, you should specify them in the prototype in the header file, and only in the prototype in the header file