关闭

C++中类的细节说明

标签: c++
631人阅读 评论(0) 收藏 举报
分类:



1、前言


C++中提供了一种抽象数据类型的能力,就是类。通过定义类,可以方便的理解各种现实生活中有实际意义的抽线模型,方便开发中进行调试,编写和修改程序。类可以隐含自己的成员不被外界访问也可以开放自己的成员使得外界可以访问,这就构成了很好的封闭模式。接下来,会对类的作用域,构造函数,this指针以及友元函数,可变成员和静态成员进行描述,这些都是定义类的细节。


2、类的组成部分


2.1类成员

类中可以定义数据成员也可以定义函数成员,可以使用访问修饰符修饰它们,比如使用private就使得它们只能在类里面被访问。对于成员的数量并没有要求,我们需要根据实际类型去定义。


2.2构造函数初始化列表

构造函数初始化列表,一般是以构造函数名称+形参表+:+成员变量(初始值)组成。看下面代码:

<pre name="code" class="cpp">class Person
{
private:
       Person():name("hy"),age(20){}
public:
        string name;
        int age;

}

2.3成员函数的声明和定义

在类内部声明成员函数是必须的,而成员函数的定义则是可选的。如果在类的内部定义成员函数,相当于内联函数,在类的外部定义函数,则必须声明函数的作用域,即该函数属于哪个类。
<pre name="code" class="cpp">class Person
{
private:
       Person():name("hy"),age(20){}
public:
        string name;
        int age;
        void addAge()
         {
             age++;
         }//等同于内联函数

}

//外部定义函数必须声明类空间int Person::getAge(){return age;}

2.4同一类型的数据成员

如果一个类含有多个同一类型的数据成员,则这些数据成员可以在同一行中声明:
class Person
{
private:
       Person():name("hy"),age(20){}
public:
        string name;
        int age,height;//同一行声明数据成员
        void addAge()
         {
             age++;
         }//等同于内联函数

}


2.5类内部使用别名简化操作

如果在一个类的内部,有些数据类型比较复杂,可以给他们定义一个别名,这样就可以大大简化操作了。

class Person
{
private:
       Person():name("hy"),age(20){}
      
public:
        string name;
        int age,height;//同一行声明数据成员
        void addAge()
         {
             age++;
         }//等同于内联函数
         //使用别名简化操作
        typedef std::string::size_type index;
         index size_type;

}


2.6显示指定成员函数为内联函数

在类内部定义的函数默认是内联函数,这样在调用该函数的时候,编译器将试图在同一行中将其拓展。或者我们也可以显示的用inline修饰函数为内联函数:


class Person
{
private:
       Person():name("hy"),age(20){}
public:
        string name;
        int age;
        void addAge()
         {
             age++;
         }//等同于内联函数

}



//外部定义函数必须声明类空间
inline int Person::getAge()//显示声明内敛函数
{
return age;
}

注意内联函数不应该过于复杂并且它的定义最好和类在同一个头文件中。


3、隐含的this指针

成员函数含有一个附加的this指针形参,用于指向调用对象。和一般的指针一样,我们可以调用它来解引用获得成员变量的值。也可以使用它来操作调用对象的整体。比如:


class Person
{
private:
       Person():name("hy"),age(20){}
public:
        string name;
        int age;
        void addAge()
         {
             age++;
         }//等同于内联函数

}



//外部定义函数必须声明类空间
inline int Person::getAge()//显示声明内敛函数
{
return age;
}

//使用隐含的this指针
Person& Pserson::setAge(int age)
{
this->age=age;
return this;
}


4、以const结尾的成员函数


一般的成员函数的this指针是一个指向非const数据类型的const指针,即可以该表this指向的对象的成员变量的值,但是不可以修改this指针指向的值。如果我们希望声明一个指向const类型的const指针的话,可以用const修饰函数:

string Person::displayName() const
{
return name;
}

这样子的话,就不可以通过this指针去修改任何Person对象的数据成员了。



5、可变数据成员


如果一个成员函数被声明为const函数,那么我们是不能通过this指针去修改成员变量的。但是如果类中有些成员变量,无论什么状态下都应该是可以改变的,怎么定义呢。可以用multable修饰符修饰它,这样无论函数是否为const,都可以修改它的值。

class Person
{

private:
         multable int height;
         string name;
}

string  Person::getName(int height)const
{
height++;
return name;
}

例子不重要,关注的是用法,可以看到即使是const成员函数,由于height用multable声明了,所以仍然是可以改变的。



6、使用类的成员


访问类的结构成员可以使用成员操作符和指针操作符。

pPerson->name;

person.name;


7、构造函数


构造函数的目的是初始化成员变量,每个类都会有一个构造函数,同时我们也可以重载构造函数。C++中的构造函数不能是const函数,因为构造函数本身就是用来修改值得。

person();

person(const &istream);

person(const &name);


8、构造函数初始化列表

考虑下面两种初始化方法:

person(string name):name(name),age(20){}

person(string name)
{
this->name=name;
}

上面两种方法都可以给name赋值,不同的地方在于,第一种使用了构造函数初始化式,是直接在创建对象的时候就给成员变量进行值的初始化。后面这种严格意义来说是赋值初始化,因为在调用后面这种构造函数的时候,person对象已经建立了并且他的成员变量都有了默认的值,只是后来我们有重新修改了成员变量的数据而已。虽然两者的结果是一样的但是过程却不同。因为这种特性,如果类中包含的成员变量没有默认构造函数的话,就一定要用构造函数初始化式进行显示初始化,而不可以使用复制初始化的方式。



9、调用无参默认构造函数的错误实例

如果我们没有给类显示声明一个构造函数,那么编译器会给我们生成一个无参的默认构造函数。当我们调用无参默认构造函数的时候,切记不要加()。


Person person();
cout<<person.name;

Person person;
cout<<person.name;

上述两种写法,只有第二种才是对的,第一中编译器不会把它当作一个对象的定义,而是当作一个函数的声明。



10、友元函数,友元类


我们知道,一个类的成员变量声明为private的时候,外界是不允许访问它们的。比如,我在Display类中有如下方法:

void Dispaly::printlnName(Person &person)
{
cout<<person.name;
}

假设name是person的私有变量,那么上述的方法行不通的,为了让该方法可以访问persond的私有变量,需要将该函数声明为友元函数:


class Person
{
friend Display::printlnName(Person &person);
//......}

这样Display类的printlnName函数就可以访问Person的私有成员了。如果我们想让Display整个类都可以访问私有成员函数,可以:

class Person
{
friend class Display;
//......}

这样,Display的任何函数都可以访问Person的私有成员了。




11、static静态成员


我们只需要知道一点,静态成员是和类关联的,而不是和类的对象关联的,所以,就衍生除了很多特性。比如每次通过类的对象操作静态成员的时候,即使这些类的对象是不一样的,但是它们操作的静态成员是一样的。

Person
{
static string name;
//......
}

Person person1;
Person person2;

我们用person1,person2去访问静态成员name,得出的结果是一样的。

因为静态成员和类的对象没有关系,所以,如果声明了一个静态函数,是没有隐含的this指针的。

Person
{
//.......
public:
static Person& getPerson()
{
return this;
}
}


上面的写法是错的,因为getPerson是静态方法,它不和具体的对象绑定,所以是没有隐含的操作对象的。



关于类的细节就是这么多了,很简单,但是很容易被忽略,所以需要反复记忆。


---------文章写自:HyHarden---------

--------博客地址:http://blog.csdn.net/qq_25722767-----------


1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:38044次
    • 积分:824
    • 等级:
    • 排名:千里之外
    • 原创:41篇
    • 转载:0篇
    • 译文:0篇
    • 评论:7条
    最新评论