local variable
Local variables are deiined inside a method,have a scope limited to the metnod to which they belong.
int TicketMachine::refundBalance(){
int amountToRefund;//本地变量
amountToRefund = balance;
balance = 0;
return amountToRefund;
}
A local variable of the same name as a field will prevent the field being accessed from within a method.
Fields, parameters, local variables
local | glocal | member | |
lifestyle生存期 | { } | 全局 | 对象创建或销毁 |
scope作用域 | { } | 全局 | 类 |
• All three kinds of variable are able to store a value that is appropriate to their defined type.
• Fields are defined outside constructors and methods
• Fields are used to store data that persists throughout the life of an object. As such, they maintain the current state of an object. They have a lifetime that lasts as long as their object lasts.
• Fields have class scope: their accessibility extends throughout the whole class, and so they can be used within any of the constructors or methods of the class in which they are defined.
• As long as they are defined as private, fields cannot be accessed from anywhere outside their defining class.
• Formal parameters and local variables persist only for the period that a constructor or method executes. Their lifetime is only as long as a single call, so their values are lost between calls. As such, they act as temporary rather than permanent storage locations.
• Formal parameters are defined in the header of a constructor or method. They receive their values from outside, being initialized by the actual parameter values that form part of the constructor or method call.
• Formal parameters have a scope that is limited to their defining constructor or method.
• Local variables are defined inside the body of a constructor or method. They can be initialized and used only within the body of their defining constructor or method.
• Local variables must be initialized before they are used in an expression – they are not given a default value.
• Local variables have a scope that is limited to the block in which they are defined. They are not accessible from anywhere outside that block.
C++ access control
• The members of a class can be cataloged, marked as:
– public
– private
– protected
public
• public means all member declarations that follow are available to everyone.
• Example: Public.cpp
Struct A{
//未声明public,说明都是public
int i;
char j;
float t;
void func();
};
void A::func(){}
struct B{
public:
int i;
char j;
float t;
private:
void func();
};
void B::func(){}
int main(){
A a;
B b;
a.i = b.i = 1;
a.j = b.j = 'c';
a.t = b.t = 3.14159;
a.func();
b.func();
}
private
• The private keyword means that no one can access that member except inside function members of that type.
• Example: Private.cpp
struct B{
public:
int i;
void func();
private:
char j;
float t;
};
void B::func(){
i = 0;
j = '0';
t = 0.8;
}
int main(){
B b;
b.i = 1;//ok,public
b.j = '1';//Illegal,private
b.t = 1.0;//Illegal,private
}
修改
struct B{
public:
int i;
void func();
void ff(B* p);
private:
char j;
float t;
};
void B::func(){
i = 0;
j = '0';
t = 0.8;
}
void B:: ff(B* p){
p -> j = 'A';
}
int main(){
B b;
B bb;
b.ff(&bb);//虽然bb的j是private,但可以用b的ff函数访问
}
private的边界是类,不是对象
Friends友元
• to explicitly grant access to a function that isn’t a member of the structure
• The class itself controls which code has access to its members.
• Can declare a global function as a friend, as well as a member function of another class, or even an entire class, as a friend.
• Example: Friend.cpp
struct X;
struct Y{
void f(x*);
};
strcut X{
private:
int i;
public:
void initialize();
friend void g(X*, int);//全局友元
friend void Y::f(X*);//结构体函数友元
friend strcut Z;//整个结构体是友元
friend void h();
};
void X::initialize(){
i = 0;
}
void g(X* x, int i){
x -> i = 47;
}
void Y::f(X* x){
x -> i = 47;
}
class vs. struct
• class defaults to private
• struct defaults to public.
• Example: Class.cpp
class B{
int i, j, k;//不在public里,说明是private
public:
int f();
void g();
};
对类来说,没有声明访问属性,默认是private;而结构体默认的访问属性是public
Initialization
Member Init
• Directly initialize a member
• benefit: for all ctors
• Only C++11 works
Initializer list
class Point {
private:
const float x, y;//const表示成员变量一旦赋值就不能被修改
Point(float xa = 0.0, float ya = 0.0)
: y(ya), x(xa) {}
};
/*:{} —— 初始化列表,只有构造函数能使用,会在构造函数执行之前调用y,x的构造函数,将其初始化。
初始化顺序是按照定义的顺序,不是初始化列表的顺序
*/
• Can initialize any type of data
– pseudo-constructor calls for built-ins
– No need to perform assignment within body of ctor
• Order of initialization is order of declaration
– Not the order in the list!
– Destroyed in the reverse order.
#include <iostream>
#include <iomanip>
using namespace std;
class Point{
private:
const int x, y;
public:
Point(int ax, int ay);
};
Point::Point(int ax, int ay){
x = ax;
y = ay
}
int main(){
Point p(1, 2);
}
/*
报错,因为用了const,不能被赋值,只有在初始化的时候指定值,如const int a = 1;
*/
Initialization vs. assignment初始化和赋值
Student::Student(string s):name(s) {}
initialization
before constructor
Student::Student(string s) {name=s;}
assignment
inside constructor
string must have a default constructor
class Point{
private:
const int x, y;
public:
Point(int ax, int ay);
};
Point::Point(int ax, int ay):x{ax}, y{ay}{
}
class Rectangle{
private:
Point p1, p2;
public:
Rectangle(int x1, int y1, int x2, int y2);
}
Rectangle::Rectangle(int x1, int y1, int x2, int y2){
}
//会报错,p1, p2缺少默认构造函数
int main(){
Point p(1, 2);
}
修改
class Point{
private:
const int x, y;
public:
Point(int ax, int ay);
Point():x(0), y(0){cout << 'def' << endl;}
};
Point::Point(int ax, int ay):x{ax}, y{ay}{
cout << "Point" << endl;
}
class Rectangle{
private:
Point p1, p2;
public:
Rectangle(int x1, int y1, int x2, int y2);
}
Rectangle::Rectangle(int x1, int y1, int x2, int y2){
}
//会报错,p1, p2缺少默认构造函数
int main(){
Point p(1, 2);
Rectangle(1,2,3,4);
}
/*
输出:
Point
def
def
*/
Function overloading 函数重载
• Same functions with different arguments list.
void print(char * str, int width); // #1
void print(double d, int width); // #2
void print(long l, int width); // #3
void print(int i, int width); // #4
void print(char *str); // #5
print("Pancakes", 15); 1
print("Syrup"); 5
print(1999.0, 10);2
print(1999, 12); 4
print(1999L, 15); 3
Example: leftover.cpp
unsigned long left(unsigned long num, unsigned cl);
char* left(char* str, int n = 1);
int main(){
using namespace std;
char* trip = "Ha";
unsigned long n = 12345678;
int i;
char* temp;
for(i = 1; i < 10; i++){
cout << left(n, i) << endl;//第一个
temp = left(trip, i);//第二个
cout << temp << endl;
delete [] temp;
}
return 0
}
Overload and auto-cast
void f(short i);
void f(double d);
f(‘a’); //cahr类型
f(2); //int
f(2L); //long
f(3.2);//用double
前面三种都会报错
Default arguments
• A default argument is a value given in the declaration that the compiler automatically inserts if you don’t provide a value in the function call.
Stash(int size, int initQuantity = 0);
调用时可以只给一个值,会给size
• To define a function with an argument list, defaults must be added from right to left.
int harpo(int n, int m = 4, int j = 5);
int chico(int n, int m = 6, int j);//illeagle 如果给两个值,无法分辨第二个值给m还是j
int groucho(int k = 1, int m = 2, int n = 3);
beeps = harpo(2);
beeps = harpo(1,8);
beeps = harpo(8,7,6);
Example: left.cpp
#include <iostream>
const int ArSize = B0;
char* left(char* str, int n = 1);
int main(){
using namespace std;
char sample(ArSize);
cout << "Enter a string:\n";
cin.get(sample.ArSize);
char* ps = left(sample, 4);//n等于4
cout << ps << endl;
delete [] ps;
ps = left(sample);//n为默认值1
cout << ps << endl;
delete[] ps;
return 0;
}
Pitfall of default arguments
The default arguments are declared in its prototype(原型),not defined in its function head
Can not put default arguments in definition May be changed by ill-formed prototype
Can not put default arguments in definition
void f(int i, int j = 10);
int main(){
f(1, 2);
f(1);
}
void f(int i, int j = 10){//声明和定分开时,默认参数不能写在定义的地方
cout << j << endl;
}
void f(int i, int j = 10){//声明和定义合并时,默认参数可以写在定义的地方
cout << j << endl;
}
int main(){
f(1, 2);
f(1);
}
//报错
void f(int i, int j = 10);
void f(int i, int j = 10){
cout << j << endl;
}
int main(){
f(1, 2);
f(1);
}
May be changed by ill-formed prototype
//会报错,因为有默认参数,不构成重载当只传入一个车参数时,会混淆
void f(int i, int j = 100);
void f(int k);
Overhead for a function call 函数调用开销
• the processing time required by a device prior to the execution of a command
• Push parameters
• Push return address
• Prepare return values
• Pop all pushed
Inline function 内联函数
• An inline function is expanded in place, like a preprocessor macro, so the overhead of the function call is eliminated.
int f(int i){
return i * 2;
}
main(){
int a = 4;
int b = f(a);
}
inline int f(int i){
return i * 2;
}
main(){
int a = 4;
int b = f(a);
}
使用incline,不会编译产生f函数,调用函数时会把f的代码嵌入到调用的位置
inline int plusOne(int x);
inline int plusOne(int x) {return ++x; };
• Repeat inline keyword at declaration and
definition.
• An inline function definition may not generate any code in .obj file.
.h | a.cpp | 编译 | 解释 |
无inline | 无incline | 正确 | 正常 |
incilne | incline | warning,link | a.o没有函数,链接函数发现main.o需要函数,但没在a.o中找到,连接错误 |
incline | 无incline | warning | main.o调用a.o的函数 |
incline函数的body不是definition,而是decalration
如果要用incline函数,需要把整个函数体放到头文件,不能把声明放在头文件,定义放在.cpp
Inline functions in header file
• So you can put inline functions’ bodies in header file. Then #include it where the function is needed.
• Never be afraid of multi-definition of inline
functions, since they have no body at all.
• Definitions of inline functions are just declarations.
Tradeoff of inline functions
• Body of the called function is to be inserted into the caller.
• This may expand the code size but deduces the overhead of calling time. So it gains speed at the expenses of space.
• In most cases, it is worth. It is much better than macro in C. It checks the types of the parameters.
与宏区别
宏没有类型检查,inline可以
#define f(a) (a)+(a)
main() {
double a=4;
printf(“%d”,f(a));
}
inline int f(int i) {
return i*2;
}
main() {
double a=4;
printf(“%d”,f(a));
}
Inline may not in-line
• The compiler does not have to honor your request to make a function inline. It might decide the function is too large or notice that it calls itself (recursion is not allowed or indeed possible for inline functions), or the feature might not be implemented for your particular compiler.
Inline inside classes
• Any function you define inside a class declaration is automatically an inline.
• Example: Inline.cpp
class Point{
int i, j, k;
public:
Point(){i = j = k = 0;}
Poing(int li, int lj, int lk){i = li, j = lj, k = lk;}
void print(string& msg = ""){
if(msg.size() != 0){cout << msg << endl;}
cout << "i =" << i << ","
<< "j =" << j << ","
<< "k =" << k << endl;
}
};
body出现在类内的函数就是incline函数,不需要加incline关键字
Access functions 用来访问每个成员变量的值
class Cup{
int color;
public:
int getColor(){return color;}
void setColor(int color){
this -> color = color;
}
};
• They are small functions that allow you to read or change part of the state of an object – that is, an internal variable or variables
Pit-fall of inline
• You can put the definition of an inline member
function out of the class braces.
• But the definition of the functions should be put before where they may be called.
• Example: NotInline.h, NotInline.cpp, NotInlineTest.cpp
Reducing clutter
• Member functions defined within classes use the Latin in situ (in place) and maintains that all
definitions should be placed outside the class to
keep the interface clean.
• Example: Noinsitu.cpp
class Rectangle{
int width, height;
public:
Rectangle(int w = 0, int h = 0);
int getWidth() const;
void setWidth(int w);
int getHeight()const;
void setHeight(int h)
};
inline Rectangle::Rectangle(int w, int h):width(w), height(h){}
inline int Rectangle::getWidth() const{
return width;
}
类内成员函数声明时不是incline,但定义时指明inline
Inline or not?
• Inline:
• Small functions, 2 or 3 lines
• Frequently called functions, e.g. inside loops
• Not inline?
• Very large functions, more than 20 lines
• Recursive functions 递归函数
• A lazy way
• Make all your functions inline
• Never make your functions inline