美文网首页
C++ 面向对象之二

C++ 面向对象之二

作者: DejavuMoments | 来源:发表于2019-04-06 16:53 被阅读0次

const member functions

为什么在函数名和函数体之间加 const

class complex{
public:
    // 初始化列表
    complex (double r = 0, double i = 0): re(r), im(i) {}
    
    // 运算符重载
    complex operator += (const complex);
    
    // 为什么在函数名和函数体之间加 const ?
    // 这里只是拿出来数据,并不会改变数据内容
    // 不改变数据内容的函数,马上加上 const
    // 该加一定要加
    double real() const { return r; }
    double imag() const { return i; }
private:
    double re, im;
    friend complex& __doapl (complex*, const complex&);
}

在设计接口的时候,需要加 const 的话,一定要加上 const。

不加上 const 会有什么后果?

// 加上 const 的情况,以下是 ok 的
{
    complex c1(2, 1);
    cout << c1.real();
    cout << c1.imag();
}

// ??
/* 
const 出现在了对象/变量的前面,表示其是不可以更改的
如果在这种情况下,complex 类中 real() 和 imag() 不加上 const ,
意思就是这两个函数可能会改 data
此时,类的 user 在这里加上 const 明确表示 c1 不可以更改的,
而 complex 类中却没有加 const,表示可以更改 data,这里就产生矛盾了
所以,编译器运行在这里会报错
*/
{
    const complex c1(2, 1);
    cout << c1.real();
    cout << c1.imag();
}

规范化的 C++ 写法!!!

参数传递:

pass by value v.s. pass by reference(to const)

class complex{
public:
    complex (double r = 0, double i = 0): re(r), im(i) {}
    
    // & and const
    complex operator += (const complex&);
    double real() const { return r; }
    double imag() const { return i; }
private:
    double re, im;
    // & and const
    friend complex& __doapl (complex*, const complex&);
}

// 第一个参数传进来没有 const ??
ostream& operator << (ostream& os, const complex& x)
{
    return os << '(' << real(x) << ',' << imag(x) << ')';
}

double 4个字节

尽量不要 pass by value

值传递

过去在 C 中可以传递指针:传递的东西太大了,怎么办呢?就把这个东西的地址传过去。指针 4 个字节,速度会很快。

C++ 中有 reference。

引用在底层就是一个指针,所以传引用就相当于传指针那么快,形式比指针漂亮!

所以我们可以的话,尽量所有的参数传递都传引用。(速度更快啊)

特例:字符一个字节,引用四个字节。为什么不穿字符的值呢?在这种情况下,也可以。

那么问题来了,我们传引用如果只是为了速度,但是并不想被修改,该怎么办呢?

传引用/指针可能会修改原始数据,但是我们不想原始数据被改动,那么我们可以加上 const,这样的话如果实际情况发生修改的话,编译的时候就会出错。

返回值传递

return by value and return by reference(to const)

reference 也可以用于返回值的传递

传引用速度很快,就是传指针的速度。

返回值的传递尽量 Pass by Reference

class complex{
public:
    complex (double r = 0, double i = 0): re(r), im(i) {}
    
    // & and const
    // 返回的类型:return by reference
    // complex& 
    complex& operator += (const complex&);
    
    // return by value
    double real() const { return r; }
    double imag() const { return i; }
private:
    double re, im;
    
    // & and const
    // do assignment plus
    // 返回的类型:return by reference
    // complex&
    friend complex& __doapl (complex*, const complex&);
}

// 第一个参数传进来没有 const
ostream& operator << (ostream& os, const complex& x)
{
    return os << '(' << real(x) << ',' << imag(x) << ')';
}

friend

class complex{
public:
    complex (double r = 0, double i = 0): re(r), im(i) {}
    
    complex& operator += (const complex&);
    double real() const { return r; }
    double imag() const { return i; }
private:
    // 实部和虚部 放在 private 中,表示不想让外界可以任意访问实部和虚部
    // 外界访问实部和虚部可以通过 public 中的函数来获取
    double re, im;
    
    // 加 friend 表示该函数是 class 的 friend ,可以直接操作实部和虚部
    // 这里是 __doapl 函数的声明
    friend complex& __doapl (complex*, const complex&);
}

// 这是 __doapl 函数的定义
// 自由取得 friend 的 private 成员(并不需要通过某个函数)
inline complex&
__doapl (complex* ths, const complex& r)
{
    ths->re += r.re;
    ths->im += r.im;
    return ths;
}

通过函数拿数据稍微慢一点, 通过 friend 是直接拿,会快一点。

可是 friend 破坏了 封装性,要设计者自己来权衡。

相同 class 的各个 object 互为 friends, 所以可以这样:

class complex{
public:
    complex (double r = 0, double i = 0): re(r), im(i) {}
    complex& operator += (const complex&);
    double real() const { return r; }
    double imag() const { return i; }
    
    //
    int func(const complex& param){
        return param.re + param.im;
    }
    
private:
    double re, im;
};


{
    complex c1(2, 1);
    complex c2;
    
    // 在这里竟然可以直接拿另外一个 object 中的 private 属性 ?!
    c2.func(c1);
}

class body 外各种定义

什么情况下可以 pass by reference
什么情况下可以 return by reference
加不加 const ? 看情况。

构造函数的特殊语法: initialization list 尽量使用

什么时候不能 return by reference ?

c1 += c2 运算结果放在 c1,可以传引用出去。

c1 + c2 运算结果,必须放在函数新创建的新的东西里(local 变量),这时候就不是 返回 reference, 因为在函数内创建的那个东西,在函数调用结束就没有了,如果把引用传出去的话,会出问题。

相关文章

  • C++ 面向对象之二

    const member functions 为什么在函数名和函数体之间加 const? 在设计接口的时候,需要加...

  • CPP基础:面向对象编程

    面向对象编程 类 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核...

  • C++ — 类 & 对象超详解

    C++ 类 & 对象 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ ...

  • 好好干

    C语言面向过程 C++面向对象

  • boolan/C++面向对象高级编程 part3

    C++面向对象高级编程 part3 @(boolan C++)[C++] 概述 面向对象的三种关系 composi...

  • C++零基础教程之类和对象初识

    C++ 类和对象 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核...

  • C++面向对象

    C++类和对象 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心...

  • cpp面向对象

    面向对象编程 [TOC] 类 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 ...

  • C++ 类 & 对象

    原文地址:C++ 类 & 对象 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是...

  • 类与对象的哲学关系

    从C到C++的发展历程可以全面了解面向过程到面向对象的过程 面向对象的概念: 理解面向对象: ...

网友评论

      本文标题:C++ 面向对象之二

      本文链接:https://www.haomeiwen.com/subject/eagriqtx.html