Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > c++学习笔记(四)——类(2)
【标  题】:c++学习笔记(四)——类(2)
【关键字】:c++
【来  源】:http://www.cublog.cn/u/11794/showart.php?id=143293

c++学习笔记(四)——类(2)

Your Ad Here

l           成员函数&&非成员函数

Eg

#include<iostream>

using namespace std;

class Student{

    public:

       void p(){

           age=20;

           cout<<age;

       }

       int q(){return(age);}//成员函数q

       float score;

    private:

        char name[9];

        int age;

};

void p(int a) //非成员函数p

 {

   cout<<a;

}

void main()

{

       Student  a;

    void p(int);

    a.p();

    p(a.q());

}

l           内联函数

何为内联函数?inline、调用之前inline显性定义或者声明(而且声明和定义要一致出现内联关键字

小的成员函数一般在类内定义,一般默认为内联函数)

复杂语句(循环、多分支)不允许(如出现则不视为内联)

C++的工程实现

C++的函数调用机制  介绍函数声明机制

类成员函数不存在于定义类的头文件中,即可以在类定义{}外定义;

为了保证效率尽可能的类内定义,以保证系统自动安排是否内联

l           类的定义和调用的分离

Eg

//student.h

#include<iostream>

using namespace std;

class student

{

public:

       void p();

       float score;

protected:

        char name;

        int age;

};

 

//p.cpp

#include"student.h"

void student::p()

{

       age = 19;

    cout<<age;

}

 

//main.cpp

#include"student.h"

void main()

{

       student a;

       a.p();

}

将类的定义和类的成员函数分离放在不同文件中避免了函数重复定义的混乱。

l           This

this是一个指针,(一个内部调用),所以使用它访问成员时,用->而不是.

Eg:

//student.h

#include<iostream>

using namespace std;

class student

{

public:

       student *p(void);

          student &q(void);

          void s(int);

       float score;

protected:

        char name;

        int age;

};

//p.cpp

 

#include"student.h"

void student::s(int a)

{

       this->age=a;

}

student *student::p()

{

       age=age+2;

    return this;//this返回指针(地址)

}

student &student::q()

{

       age=age+2;

       return(*this);//返回引用(指针的值)

}

//main.cpp

#include"student.h"

void main()

{

       student a;

       a.s(20);

       a.score=70;

       a.p()->score++;//返回的是指针,使用->

       a.q().score++;//返回的是引用,相当于别名使用.

       cout<<a.score;

}

l           变量重名

Student.h

class Student{

  public:

 float q(void)

 float score;

  protected:

     float m;

};

int Student; 允许重名

class Student a;

l           Stack(栈)

Eg

//stacks.h

class stack //定义类

{

public:

       void put(int);

       int pop(void);

private:

       int a;

       stack *head,*next;

};//注意,这里的分号不能没有

//stack1.cpp,实现类的成员函数

#include"stacks.h"

void stack::put(int k)

{

       stack *p=new stack;

       p->a=k;

       p->next=head;

       head=p;

}

int stack::pop()

{

       stack *temp;

       int k;

       temp=head;

       head=head->next;

       k=temp->a;

       delete temp;

       return k;

}

//main.cpp,主函数

#include <iostream>

#include"stacks.h"

using namespace std;

void main()

{

       stack *p=new stack;//注意,指针是地址,在使用前必须初始化

       p->put(10);

       p->put(20);

       cout<<p->pop();

       cout<<p->pop();

       delete p;//在使用结束后释放内存空间

}

l           函数重载

    参数类型、参数个数,参数顺序都可以成为重载借口。返回值类型不能够作为重载依据,要求同一个作用域

函数重载的次序:

1.       首先严格匹配

2.       其次相容类型匹配

3.       最后用户定义类型转换(构造函数||运算符重载),尽量避免类型相容二义性。

 

l           函数默认参数

Eg

#include<iostream>

using namespace std;

int x(int i=10,int j=20,int k=30)

{

       return i+j+k;

}

void main()

{

cout<<x()<<endl;

cout<<x(15)<<endl;

cout<<x(15,25)<<endl;

cout<<x(15,25,35)<<endl;

}

注意:

1.       默认值从右端开始设置,匹配从左端开始匹配。这样的定义是错误的:int x(int i=10,int j,int k=30)

2.       同一作用域内同一函数允许被多次声明

3.       有默认值时不再允许有多次声明。

4.       默认值相同也不允许

理由:可能产生二义性:

void x(int i=10)

{

     cout<<i<<"11111";

}

void x()

{

       cout<<"22222";

}

void main()

{

x();

}

所以应该避免重载过程中的涉及参数个数的默认设置。

l           typedef

typedef int integer;

integer i=2;

typedef float real;

real k=10.10;

typedef char * STRING;

STRING p;

STRING a[10];

typedef  struct Student * NODE;

NODE  b,c;

l           模板&函数

Eg

#include<iostream>

using namespace std;

template <typename T>

void change(T &a)

{

       a=a+2;

}

template <typename Q>

void swap1(Q &a,Q &b)

{

       Q temp;

       temp=a;

       a=b;

       b=temp;

}

template <typename K>

K add(K a,K b)

{

       K temp;

       temp=a+b;

       return temp;

}

void main()

{

       int a=2,b=2;

       float k=3.1;

       change(a);

       swap1(a,b);

       cout<<a<<b<<endl;

       cout<<add<int>(a,k)<<endl;//对于类型不匹配的,可以进行强制类型转换,float类型被转换为int

       //swap1<int>(a,k);//注意,这样是错误的,但这不是因为模板的原因引起的,而是因为引用自身的原因引起的。请看下面的例子

}

void main()

{

       int a=1;

   float & b = a;//错误

   float & c = int(a);//错误

   float const & d = a;//正确

}

注意:在引用中,显示转换在类型不一样时是错误的。原因:类型长度不匹配;如int 4字节,double 8字节。

template<typename T,typename U>

void add(T& a,U & b)

{  cout<<a+b<<endl;}

void main(){

int x=1,y=2;

float s=3.0,t=4.0;

add(x,y);

add(s,t);

add(x,t);

add(s,y);

}//以上四条语句均正确;因为TU可以相同也可以不相同

template<typename T,typename U>

void add(T& a,U & b)

{  cout<<a+b<<endl;}

void swap(T& a,T & b)//错误

{  T temp = a; a = b; b = temp;}

void main(){

int x=1,y=2;

float s=3.0,t=4.0;

add(x,y);

swap(s,t);

}//模板类型声明不能共享;typename不能节省

template <typename T>

void swap(T &a,T &b)

{

 T temp=a;

 a=b;

 b=temp;

}

void swap(int * &a,int * &b)

{

 int temp=*a;

 *a=*b;

 *b=temp;

}

void main()

{

       int a=1,b=2;

       swap(a,b);

       cout<<a<<b<<endl;

       float i=5.1,j=5.2;

       swap(i,j);

       cout<<i<<j<<endl;

       int *p=&a,*q=&b;

       swap(p,q);

       cout<<*p<<*q<<endl;

}//优先匹配非模板函数

 

l           名字空间namespace

  1namespace的定义可以是不连续的(即namespace的定义是可以积累的),即,同一个namespace可以在不同的文件中定义,分散在不同文件中的同一个namespace中的内容彼此可见。这对生成一个库很有帮助,可以使我们更容易将库的源代码组织成接口和实现部分。如:在头文件(.h文件)的名字空间部分定义库接口;在实现文件(如.c.cpp文件)的名字空间部分定义库实现。名字空间定义可积累的特性是向用户隐藏实现细节必需的,它允许把不同的实现文件(如.c.cpp文件)编译链接到一个程序中,而不会有编译错误和链接错误。

  2、全局名字空间成员,可以用“::member_name”的方式引用。当全局名字空间的成员被嵌套的局部域中声明的名字隐藏时,就可以采用这种方法引用全局名字空间成员。
  3、名字空间成员可以被定义在名字空间之外。但是,只有包围该成员声明的名字空间(也就是该成员声明所在的名字空间及其外围名字空间)才可以包含它的定义。
  尤其要注意的是#i nclude语句的次序。假定名字空间成员mynamespace::member_i的声明在文件dec.h中,且#i nclude "dec.h"语句置于全局名字空间,那么在include语句之后定义的其他名字空间内,mynamespace::member_i的声明均可见。即,mynamespace::member_i可以在#i nclude "dec.h"之后的任何地方任何名字空间内定义。
  4、未命名的名字空间。我们可以用未命名的名字空间声明一个局部于某一文件的实体。未命名的名字空间可以namespace开头,其后不需名字,而用一对花括号包含名字空间声明块。如:

代码:

// 其他代码略
namespace
{
        void mesg()
        {
               cout<<"**********\n";
        }
}
int main()
{
        mesg(); //正确
        
    //...
 
        return 0;
}


  由于未命名名字空间的成员是程序实体,所以mesg()可以在程序整个执行期间被调用。但是,未命名名字空间成员只在特定的文件中可见,在构成程序的其他文件中是不可以见的。未命名名字空间的成员与被声明为static的全局实体具有类似的特性。在C中,被声明为static的全局实体在声明它的文件之外是不可见的。

using
关键字
  1using声明与using指示符:前者是声明某名字空间内的一个成员,后者是使用整个名字空间。例如:

代码:

using cpp_primer::matrix; // ok,using声明
using namespace cpp_primer; //ok,using指示符


  2、该using指示符语句可以加在程序文件的几乎任何地方,包括文件开头(#i nclude语句之前)、函数内部。不过用using指定的名字空间作用域(生命周期)受using语句所在位置的生命周期约束。如,函数内部使用“using namespace myspacename;” myspacename仅在该函数内部可见。
  3、可以用using语句指定多个名字空间,使得多个名字空间同时可见。但这增加了名字污染的可能性,而且只有在使用各名字空间相同成员时由多个using指示符引起的二义性错误才能被检测到,这将给程序的检测、扩展、移植带来很大的隐患。因此,因该尽量使用using声明而不是滥用using指示符

预处理操作符'#'和'##':【上一篇】
一段求平方根的代码:【下一篇】
【相关文章】
  • visual c++ 6.0中使用winpcap
  • C++学习日志四
  • c++学习笔记(五)——对象生灭
  • c++学习笔记(六)——友元
  • 在Eclipse下的C/C++开发(Eclipse3.2 + CDT 3.1)
  • C++:memset ,memcpy 和strcpy 的根本区别?-
  • VC++动态链接库((DLL)编程深入浅出(一)
  • VC++动态链接库((DLL)编程深入浅出(二)
  • "COM as a better C++"读后小结
  • VC++ Studio若干小技巧
  • 【随机文章】
  • Adobe CS2新丁Bridge新鲜试用体验
  • 三层交换机技术分析
  • J2ME开发环境的安装和使用
  • 如何让PowerDesigner支持自动生成含SQL Server 2000的表和列注释的脚本[转]
  • 系统中快速访问文件夹两法
  • Pro OGRE 3D Programming 电子版
  • 第十课 (10)Linux备份与压缩命令
  • XML的定义
  • 痘痘的位置如何治疗下巴痘痘怎么治疗痘痘去痘痘的方法康本告诉你下巴长痘痘的原因
  • 用CB动态改变显示器分辨率
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.