第一章 关于对象

2018-06-27  本文已影响0人  武术队总教练

声明一个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)
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.1 C++对象模型

已知下面的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++对象模型

加上继承

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

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

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


虚拟继承

1.2 关键词所带来的差异

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;
    }
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++以下列方法支持多态

shape *ps = new Circle();
ps->rotate();
if( circle *pc = dynamic_cast<Circle *>(ps))
    ...

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

指针的类型

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

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

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

ZooAnimal za("Zoey");
ZooAnimal *pza = &za;
非派生class的obejct布局和pointer布局

加上多态之后

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机制。

上一篇 下一篇

猜你喜欢

热点阅读