美文网首页
第一章 关于对象

第一章 关于对象

作者: 武术队总教练 | 来源:发表于2018-06-27 15:47 被阅读0次
  • C语言:数据与函数分开

声明一个struct Point3d

typedef struct point3d
{
    float x;
    float y;
    float z;
}Point3d;

打印一个Point3d,定义函数或者宏

void Point3d_print(const Point3d *pd)
{
    printf("(%g, %g, %g)", pd->x, pd->y, pd->z);
}
#define Point3d_print( pd ) \
    printf("(%g, %g, %g)", pd->x, pd->y, pd->z);

或者直接在程序中完成操作

void my_foo()
{
    Point3d *pd = get_a_point();
    printf("(%g, %g, %g)", pd->x, pd->y, pd->z);
}

某个点的特定坐标值可以直接存取

Point3d pt;
pt.x = 1.0;

也可以经由一个前置处理宏来完成

#define X(p, xval) (p.x) = (xval);
X(pt, 0.0)
  • C++中,Point3d采用ADT来实现
class Point3d
{
public:
    Point3d(float x = 0.0, float y = 0.0, float z = 0.0)
        : _x(x), _y(y), _z(z) {}

    float x() const { return _x; }
    float y() const { return _y; }
    float z() const { return _z; }

    void x(float xval) { _x = xval; }
    void y(float yval) { _y = yval; }
    void z(float zval) { _z = zval; }

private:
    float _x;
    float _y;
    float _z;
};

//输入输出运算符必须是非成员函数
//const对象只能调用const成员函数
inline ostream& operator<<(ostream &os, const Point3d &pt)
{
    os << "(" << pt.x() << ", " << pt.y() << ", " << pt.z() << ")";
    return os;
}

也可以以一个双层或三层的class结构完成

class Point
{
public:
    Point(float x = 0.0) : _x(x) {}

    float x() const { return _x; }
    void x(float xval) { _x = xval; }
protected:
    float _x;
};

class Point2d : public Point
{
public:
    Point2d(float x = 0.0, float y = 0.0)
        : Point(x), _y(y) {}

    float y() const { return _y; }
    void y(float yval) { _y = yval; }
protected:
    float _y;
};

class Point3d : public Point2d
{
public:
    Point3d(float x = 0.0, float y = 0.0, float z = 0.0)
        : Point2d(x, y), _z(z) {}

    float z() const { return _z; }
    void z(float zval) { _z = zval; }
protected:
    float _z;
};

坐标类型和坐标维度都可以参数化

template<typename T>
class Point3d
{
    Point3d(T x = 0.0, T y = 0.0, T z = 0.0)
        : _x(x), _y(y), _z(z) {}

    T x() const { return _x; }
    T y() const { return _y; }
    T z() const { return _z; }

    void x(T xval) { _x = xval; }
    void y(T yval) { _y = yval; }
    void z(T zval) { _z = zval; }

private:
    T _x;
    T _y;
    T _z;
};

template<typename T, int dim>
class Point
{
public:
    Point();
    Point(T coords[dim])
    {
        for (int index = 0; index < dim; index++)
        {
            _coords[index] = coords[index];
        }
    }

    T& operator[](int index)
    {
        assert(index < dim && index >= 0);
        return _coords[index];
    }

    T operator[](int index) const
    {
        assert(index < dim && index >= 0);
        return _coords[index];
    }

private:
    T _coords[dim];
};

template<typename T, int dim>
ostream& operator<<(ostream &os, const Point<T, dim> &pt)
{
    os << "(";
    for (int ix = 0; ix < dim - 1; ix++)
    {
        os << pt[ix] << ", ";
    }
    os << pt[dim - 1];
    os << ")";
    return os;
}

int main()
{
    float arr[5] = { 1,2,3,4,5.1 };
    Point<float, 5> pt(arr);
    cout << pt << endl;
    return 0;
}
  • 加上封装后的布局成本
    1.data member没有增加;
    2.non-inline member functions不在object中,只会诞生一个函数实例;
    3.inline function 在其每一个使用者身上产生一个函数实例。
    4.额外负担主要由virtual引起

1.1 C++对象模型

  • class data members: static, nonstatic
  • calss member functions: static, nonstatic, virtual

已知下面的class Point声明

class Point
{
public:
    Point(float xval);
    virtual ~Point();

    float x() const;
    static int PointCount();

protected:
    virtual ostream& print(ostream &os) const;

    float _x;
    static int _point_count;
};

C++对象模型

  • nonstatic data members 每一个class object内;
  • static data members 存放在class object之外;
  • static、nonstatic function members 存放在class object之外;
  • 每个class对应一个virtual table (vtbl);
  • 每一个class object安插一个指针(vptr),指向vtbl。vptr的设定和重置由构造函数、析构函数和拷贝赋值运算符完成。每一个class所关联的type_info object(用以支持RTTI)也由virtual table被指出来,通常放在表格的第一个slot。
  • 缺点:nonstatic data members 有所修改,应用程序代码需要重新编译


    C++对象模型

加上继承

C++支持单一继承和多重继承

class istream : virtual public ios {};
class ostream : virtual public ios {};
class iostream : public istream, public ostream {};

虚拟继承的情况下,base class不管在继承串链中被派生多少次,永远只会存在一个实例


虚拟继承
  • base class的data members直接放置于derived class obejct中;
  • virtual base class:导入virtual base class table或扩充原来的virtual table。

1.2 关键词所带来的差异

  • struct
  • class

1.3 对象的差异

  • 程序模型
    char boy[] = "Danny";
    char *p_son;
    p_son = new char[strlen(boy) + 1];
    strcpy(p_son, boy);
    if (!strcmp(p_son, boy))
    {
        printf("[%s] equals [%s]\n", p_son, boy);
    }
    delete[] p_son;
  • 抽象数据类型模型
    string girl = "Anna";
    string daughter;
    daughter = girl;
    if (girl == daughter)
    {
        cout << "[" + girl + "]" << " equals " << "[" + daughter + "]" << endl;
    }
  • 面向对象模型:base class用以提供共同的接口,需要通过base class的pointer或reference来完成多态
void check_in(Library_materials *pmat)
{
    if(pmat->late())
    {
        pmat->fine();
    }
    pmat->check_in();

    if(Lender *plend = pmat->reserved())
    {
        pmat->notify(plend);
    }
}

Library_materials thing1;
// class Book : public Library_materials {};
Book book;

thing1 = book;
// 调用Library_materials::check_in()
thing1.check_in();

Library_materials &thing2 = book;
// Book::check_in()
thing2.check_in()

C++以下列方法支持多态

  • base class指针指向derived class对象
  • 虚函数机制
  • dynamic_cast和typeid运算符
shape *ps = new Circle();
ps->rotate();
if( circle *pc = dynamic_cast<Circle *>(ps))
    ...

表现一个class object需要多少内存

  • nonstatic data members的总和大小
  • 由于alignment而padding上去的空间
  • 为了支持virtual而由内部产生的额外负担

指针的类型

指针本身所需的内存大小是固定的

class ZooAnimal
{
public:
    ZooAnimal();
    virtual ~ZooAnimal();

    virtual void rotate();
    
protected:
    int loc;
    string name;
};

ZooAnimal za("Zoey");
ZooAnimal *pza = &za;
非派生class的obejct布局和pointer布局
  • 指向地址1000的整形指针,在32位机器上,将涵盖地址空间1000~1003
  • 如果string是传统的8-bytes,那么一个ZooAnimal指针将横跨地址空间1000~1015

加上多态之后

class Bear : public ZooAnimal
{
public:
    Bear();
    ~Bear();

    void rotate();
    virtual void dance();

protected:
    enum Dances {...};
    Dances dances_known;
    int cell_block;
};

Bear b("Yogi");
Bear *pb = &b;
Bear &rb = *pb;
Derived class的object和pointer布局
Bear b;
ZooAnimal *pz = &b;
Bear *pb = &b;

// 不合法
pz->cell_block;

// ok
(static_cast<Bear *>(pz))->cell_block;

// run-time operation
if(Bear *pb2 = dynamic_cast<Bear *>(pz))
    pb2->cell_block;

// ok
pb->cell_block;

除了ZooAnimal中出现的members,不能够使用pz来直接处理Bear的任何members。唯一例外是使用virtual机制。

相关文章

  • 第一章 关于对象

    C语言:数据与函数分开 声明一个struct Point3d 打印一个Point3d,定义函数或者宏 或者直接在程...

  • 第一章 关于对象

    简单对象模型(A Simple Object Model) 一个objects是一系列的slots。members...

  • 第一章 关于对象

    1 对象模型 1.1 简单对象模型 每个slot指向一个members,包括数据以及函数members本身不在o...

  • jQueryDom的操作(1)

    第一章 如何筛选jQuery对象 操作jQuery对象,如何创建HTML DOM对象和jQuery对象 区别 检...

  • 面向对象(未完成)

    面向对象 标签(空格分隔): 面向对象 第一章:面向对象(上) 什么叫面向对象 面向过程、面向对象、两者区别 构造...

  • 《JAVA编程思想》学习笔记:第1-4章(Java概述)

    第一章、对象导论 1.1 抽象过程 面向对象编程:(OOP,Object Oriented Programming...

  • 关于对象

    1、Java不需要销毁对象 ①作用域(scope):决定了其内定义的变量名的可见性和生命周期。 ②对象的作...

  • 关于对象

    #面向对象 学习了面向对象呢,简要就是说为一切都是对象。 比如生活中的东西,衣食住行这些等等。。。 那这个面对就是...

  • 关于this对象

    this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被作为某个对象的方...

  • 关于对象……

    嘉羿和苪萣正在谈论关于对象的事儿 嘉羿:我和我对象每天都要聊天,语音啊电话啊或者是视频。 苪萣:每天都要聊吗? 嘉...

网友评论

      本文标题:第一章 关于对象

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