C++ note I

来源:互联网 发布:运维生存时间 mysql 编辑:程序博客网 时间:2024/04/28 01:00

-----------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------
左值与右值
定义
左值:指的是如果一个表达式可以引用到某一个对象,并且这个对象是一块内存空间且可以被检查和存储,那

么这个表达式就可以做为一个左值。      
右值:指的是引用了一个存储在某个内存地址里的数据。
从定义可以看出,左值其实要引用一个对象,而一个对象在我们的程序中又肯定有一个名字或者可以通过一个

名字访问到,所以左值又可以归纳为:左值表示程序中必须有一个特定的名字引用到这个值。而右值引用的是

地址里的内容,所以相反右值又可以归纳为:右值表示程序中没有一个特定的名字引用到这个值除了用地址。

左值:
Expression                Lvalue
x = 42                    x
*ptr = newvalue           *ptr
a++                       a++
b[0] = 100    b[0]
const int m = 10   m
int& f()       The function call to f()
右值:
Expression     Rvalue
100      100
a * b     The expression of a * b
int f()     The function call to f() that does not return reference

   以上这些内容都可以用定义来解释为什么这些为左值,而那些为右值。但我要特殊解释一下为什么函数的

调用只能作为右值除了这个函数返回的是引用。其实这个也非常好解释,因为如果一个函数返回的值是 内建

类型,那么这个返回值是没有办法通过一个名字或者表达式引用到的,同理如果一个函数返回的是一个对象,

那么这个对象是一个临时的,也不可能用一个名字访问到。所以函数的调用通常只能作为右值,但如果一个函

数返回引用,那么它的返回值就有意义了,因为它是另一个名字的别名,有名字了,所以它就变成了左值。

注意:左值能转化为右值,但反之不行。
哪些操作符必需左值.
Operator     Requirement
& (unary)     Operand must be an lvalue.
++ --      Operand must be an lvalue. This applies
     to both prefix and postfix forms.
= += -= *= %= <<= >>= &= ^= |=

-----------------------------------------------------------------------------------------------------------------
一些#define的用法
1.简单的define定义
#define MAXTIME 1000
这样的定义看起来类似于普通的常量定义CONST,但也有着不同,因为define的定义更像是简单的文本替换,

而不是作为一个量来使用,这个问题在下面反映的尤为突出。
2.define的“函数定义”
define可以像函数那样接受一些参数,如下
#define max(x,y) (x)>(y)?(x):(y);
#define Add(a,b) a+b;//define的定义是文本替换,c*Add(a,b)*d=c*a+b*d
另外要注意的地方:
#define pin (int*);
pin a,b;
本意是a和b都是int型指针,但是实际上变成int* a,b;a是int型指针,而b是int型变量。
这是应该使用typedef来代替define,这样a和b就都是int型指针了。
3.宏的单行定义 ,define的多行定义
4.在大规模的开发过程中,特别是跨平台和系统的软件里,define最重要的功能是条件编译。
就是:
#ifdef WINDOWS
......
......
#endif
#ifdef LINUX
......
......
#endif
可以在编译的时候通过#define设置编译环境
5.如何定义宏、取消宏
//定义宏
#define [MacroName] [MacroValue]
//取消宏
#undef [MacroName]
普通宏
#define PI (3.1415926)
带参数的宏
#define max(a,b) ((a)>(b)? (a),(b))
关键是十分容易产生错误,包括机器和人理解上的差异等等
6.条件编译
#ifdef XXX…(#else) …#endif
例如 #ifdef DV22_AUX_INPUT
#define AUX_MODE 3
#else
#define AUY_MODE 3
#endif
#ifndef XXX … (#else) … #endif
7.头文件(.h)可以被头文件或C文件包含;
重复包含(重复定义)
由于头文件包含可以嵌套,那么C文件就有可能包含多次同一个头文件,就可能出现重复定义的问题的。
通过条件编译开关来避免重复包含(重复定义)
例如
#ifndef __headerfileXXX__
#define __headerfileXXX__

文件内容

#endif
-----------------------------------------------------------------------------------------------------------------


inline修饰符--内联函数
inline解决一些频繁调用的小函数大量消耗栈空间或者是叫栈内存的问题
#include <iostream> 
#include <string> 
using namespace std;  
inline string dbtest(int a); //函数原形声明为inline即:内联函数  
void main() 

    for (int i=1;i<=10;i++) 
    { 
        cout << i << ":" << dbtest(i) << endl; 
    } 
    cin.get();   
}  
string dbtest(int a)//这里不用再次inline,当然加上inline也是不会出错的 

    return (a%2>0)?"奇":"偶"; 
}
    上面的例子就是标准的内联函数的用法,使用inline修饰带来的好处我们表面看不出来,其实在内部的工

作就是在每个for循环的内部所有调用dbtest(i)的地方都换成了(i%2>0)?"奇":"偶"这样就避免了频繁调用函

数对栈内存重复开辟所带来的消耗。
    注意:inline的使用是有所限制的,inline只适合函数体内代码简单的函数使用,不能包含复杂的结构控

制语句例如while switch,并且不能内联函数本身不能是直接递归函数(自己内部还调用自己的函数)。
  c语言中广泛被使用的#define语句,也可以做到inline的这些工作,
--------------------------------------------------------------------------
c++ 引用
引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。
引用的声明方法:类型标识符 &引用名=目标变量名;
int a; int &ra=a; //定义引用ra,它是变量a的引用,即别名
注意
    1、&在此不是求地址运算,而是起标识作用。声明引用时,必须同时对其进行初始化。
    2、声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一

种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。故:对引用求地址,就是对目标变

量求地址。&ra与&a相等。
    3、不能建立数组的引用。因为数组是一个由若干个元素所组成的集合,所以无法建立一个数组的别名。
引用的几种引用应用
1、引用作为参数
2、常引用
3、引用作为返回值
*********
4、引用和多态
引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。
class  A;
class  B:public A{……};
B  b;
A  &Ref = b; // 用派生类对象初始化基类对象的引用
Ref 只能用来访问派生类对象中从基类继承下来的成员,是基类引用指向派生类。如果A类中定义有虚函数,

并且在B类中重写了这个虚函数,就可以通过Ref产生多态效果。
--------------
引用总结
(1)在引用的使用中,单纯给某个变量取个别名是毫无意义的,引用的目的主要用于在函数参数传递中,解

决大块数据或对象的传递效率和空间不如意的问题。
(2)用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了

引用传递的安全性。
(3)引用与指针的区别是,指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使

用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
(4)使用引用的时机。流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数

、其它情况都推荐使用引用。

----------------------------------------

think   in   java对内部类有很详细的介绍!!!  
一个内部非静态类   如果想用的话,必须要和外部类对象相联系  
意思就是说:先有外部类,在有内部类(指非静态的)!  
main是个静态函数, 静态函数可以与对象无关.所以在调用静态函数的时候可以不

用生成外部对象A,然后你就想直接去new 内部类,报错啦!!!,解决方法是:
你得先实例化A才能使用B  
  A a=new   A();  
  B b=a.new B(); 

程序多有需要一个静态的入口方法,集中C++入口函数
main()是WINDOWS的控制台程序(32BIT)或DOS程序(16BIT),  
WinMain()是WINDOWS的GUI程序,  
wmain()是UNICODE版本的main(),  
_tmain()是个宏,如果是UNICODE则他是wmain()否则他是main()

--------------------------------------------------------------------------

 

 附录:

作者:baihacker
来源:http://hi.baidu.com/feixue http://hi.csdn.net/baihacker

本来是题目是:无聊时写了一点c++代码
后来发现都和虚函数有关,于是就把题目名字改了
其实我也不知道为什么要写这个,就随便写写吧。

代码只是示例了虚函数的一些应用,并不是说在该场景下这样用最好,甚至于说,几乎不会出现这样的用法。
但这可以让初学者加深对虚函数的理解。

C/C++ code
//继承多个接口,但是有相同的方法#include <iostream>using namespace std;class IHello{public: virtual void Say() = 0;};class IWorld{public: virtual void Say() = 0;};class MHello : public IHello{public: void Say(){cout << "Hello ";}};class MWorld : public IWorld{public: void Say(){cout << "World" << endl;}};class CObject : public MHello, public MWorld{};int main(){ CObject o; IHello& ih = o; IWorld& iw = o; ih.Say(); iw.Say(); return 0;}

 

C/C++ code
//两个平行类,通过被继承,虚函数,将下一个动作传到另一个类,V形转发#include <iostream>using namespace std;class Hello{public: void Say(){cout << "Hello ";nextH();} virtual void nextH(){}};class World{public: void Say(){cout << "World";nextW();} virtual void nextW() {}};class CObject : public Hello, public World{public: void nextH() { World::Say(); } void nextW() { ; }};int main(){ CObject o; o.Hello::Say(); return 0;}

 

C/C++ code
//受到上面平行类的启发,利用菱形继承,提供数据,实现一个switch,处理类是平行的//但是对每个平行类要有不同签名的调用下一个的虚函数,并且在CObject中对这个处理过程进行编码#include <iostream>using namespace std;class Data{public: int value;};class Case1 : public virtual Data{public: void process(){if (value == 1) {cout << 1 << endl;}else next1();} virtual void next1(){}};class Case2 : public virtual Data{public: void process(){if (value == 2) {cout << 2 << endl;}else next2();} virtual void next2(){}};class Default : public virtual Data{public: void process(){cout << "default" << endl;}};class CObject : public Case1, public Case2, public Default{public: void next1() { Case2::process(); } void next2() { Default::process(); }};int main(){ CObject o; for (int i = 0; i < 4; ++i) { o.value = i; o.Case1::process(); } return 0;}

 

C/C++ code
//想到责任链模式,也实现了一个。//但是一个处理者知道下一个处理者。#include <iostream>using namespace std;class MsgProcessor{public: MsgProcessor(MsgProcessor* next = NULL) : next_(next){} virtual void process(int msg) = 0; virtual void dispatch(int msg) { if (next_) next_->process(msg); } MsgProcessor* next_;};class Handler1 : public MsgProcessor{public: Handler1(MsgProcessor* next = NULL) : MsgProcessor(next) { } void process(int msg) { if (msg == 1) { cout << 1 << endl; } else { dispatch(msg); } }};class Handler2 : public MsgProcessor{public: Handler2(MsgProcessor* next = NULL) : MsgProcessor(next) { } void process(int msg) { if (msg == 2) { cout << 2 << endl; } else { dispatch(msg); } }};class HandlerDefault : public MsgProcessor{public: HandlerDefault(MsgProcessor* next = NULL) : MsgProcessor(next) { } void process(int msg) { cout << "default" << endl; }};int main(){ HandlerDefault dft; Handler2 h2(&dft); Handler1 h1(&h2);; for (int i = 0; i < 4; ++i) { h1.process(i); } return 0;}

 

C/C++ code
//修饰器模式,好看一点,把终止结点和非终止结点分开了。#include <iostream>using namespace std;class Component{public:virtual void process(int msg) = 0;};class CaseDefault : public Component{public: void process(int msg) { cout << "default" << endl; }};class CaseNormal : public Component{public: CaseNormal(Component* next = NULL) : next_(next) { } virtual void process(int msg) { if (next_) next_->process(msg); } Component* next_;};class Case1 : public CaseNormal{public: Case1(Component* next = NULL) : CaseNormal(next) { } void process(int msg) { if (msg == 1) { cout << 1 << endl; } else { CaseNormal::process(msg); } }};class Case2 : public CaseNormal{public: Case2(Component* next = NULL) : CaseNormal(next) { } void process(int msg) { if (msg == 2) { cout << 2 << endl; } else { CaseNormal::process(msg); } }};int main(){ CaseDefault dft; Case2 c2(&dft); Case1 c1(&c2); for (int i = 0; i < 4; ++i) { c1.process(i); } return 0;}

 

 

 

 

 

 

原创粉丝点击