栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++程序设计兼谈对象模型设计

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++程序设计兼谈对象模型设计

C++程序设计兼谈对象模型设计 转换函数
#include 

class Fraction
{
public:
  Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) {}
  operator double() const {
    return ((double)m_numerator/m_denominator);
  }
private:
  int m_numerator;   // 分子
  int m_denominator; // 分母
};

int main() {
  Fraction f(3, 5);
  double d = 4+f;
  std::cout << d << std::endl;
}

non-explicit-one-argument 构造函数

将其他类型自动转为当前类型

#include 

class Fraction
{
public:
  Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) {}
  //operator double() const {
  //  return ((double)m_numerator/m_denominator);
  //}
  Fraction operator +(const Fraction& f) const {
    return ((double)m_numerator/m_denominator);
  }
private:
  int m_numerator;   // 分子
  int m_denominator; // 分母
};

int main() {
  Fraction f(3, 5);
  Fraction d = f+4;
}

如果加上

#include 

class Fraction
{
public:
  explicit Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) {}
  Fraction operator +(const Fraction& f) const {
    return ((double)m_numerator/m_denominator);
  }
private:
  int m_numerator;   // 分子
  int m_denominator; // 分母
};

int main() {
  Fraction f(3, 5);
  Fraction d = f+4;
}

会报错

non-expllicit.cpp: 在成员函数‘Fraction Fraction::operator+(const Fraction&) const’中:
non-expllicit.cpp:8:32: 错误:could not convert ‘((double)(int)((const Fraction*)this)->Fraction::m_numerator / (double)(int)((const Fraction*)this)->Fraction::m_denominator)’ from ‘double’ to ‘Fraction’
    8 |     return ((double)m_numerator/m_denominator);
      |            ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
      |                                |
      |                                double

pointer-like classes 智能指针
template
class shared_ptr
{
public:
  T& operator*() const {
    return *px;
  }
  T* operator->() const {
    return px;
  }
  share_ptr(T* p) : px(p) {}
  
private:
  T*    px;
  long* pn;
}
迭代器

reference operator*() const {
  return (*node).data;
}

pointer operator->() const {
  return &(operator*());
}
function-like classes

重载()

namespace
#include 

namespace fraction {
  class Fraction {
  public:
    Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) {}
    operator double() const { return ((double)m_numerator / m_denominator); }

  private:
    int m_numerator;   // 分子
    int m_denominator; // 分母
  };
}

int main(int argc, char *argv[]) {

  fraction::Fraction f(3, 5);
  double d = 4+f;
  std::cout << d << std::endl;

  return 0;
}

成员模板
namespace pair_tmpl {
  template
  struct pair{
    typedef T1 first_type;
    typedef T2 second_type;

    T1 first;
    T2 second;

    pair() : first(T1()), second(T2()) {}
    pair(const T1& a, const T2& b) : first(a), second(b) {}

    // 成员模板
    template 
    pair(const pair& p)
      : first(p.first), second(p.second) {}
  };

  class base1 {};
  class Sub1 : public base1 {};

  class base2 {};
  class Sub2 : public base2 {};
}

int main(int argc, char *argv[]) {

  pair_tmpl::pair p;
  pair_tmpl::pair p2(p);

  return 0;
}

template
class shared_ptr : public __shared_ptr<_TP>
{
...
  template
  explicit shared_ptr(_Tp1* __p): __shared_ptr<_Tp>(__p) {}
...
}

base1 * ptr = new Sub1;

shared_ptr sptr(new Sub1);
specialization 模板特化

其实 模板其实就是泛化

在泛化的基础上,根据不同的类型做出不同的处理

namespace specialization {
template  struct hash {};

template <> struct hash {
  std::size_t operator()(char x) const { return x; }
};

template <> struct hash {
  std::size_t operator()(char x) const { return x; }
};

template <> struct hash {
  std::size_t operator()(char x) const { return x; }
};

} // namespace specialization


模板偏特化
  • 个数的偏特化
template
class vector
{
  ...
};

template
class vector
{
  ...
};
  • 范围的偏特化
template  class C {};

template  class C {};

C obj1;
C obj2;
模板模板参数


template  class SmartPtr> class XCls {
private:
  SmartPtr sp;

public:
  XCls() : sp(new T) {}
};

三个主题 数量不定的模板参数
namespace variadic {
  void print() {} // 最后调用到没参数的时候要做的事情

  template 
  void print(const T& firstArg, const Types&... args) {
    std::cout << firstArg << std::endl;
    print(args...);
  }
}
  • sizeof…(args)
namespace variadic {
  void print() {}

  template 
  void print(const T& firstArg, const Types&... args) {
    printf("%dn", sizeof...(args));
    std::cout << firstArg << std::endl;
    print(args...);
  }
}

auto
list c;
...
list::iterator ite;
ite = find(c.begin(), c.end(), target);

auto ite = find(c.begin(), c.end()m target);

ranged-base for
for (int i : {2, 3, 4, 5, 6, 7, 8, 9}) {
  cout << i << endl;
}

vector vec;

for (auto elem : vec) {
  cout << elem << endl;
}

for (auto& elem : vec) {
  elem *= 3;
}
Reference(重要)


namespace reference {
  typedef struct Stag {int a, b, c, d;} S;
}

int main(int argc, char *argv[]) {

  double x = 0;
  double* p = &x;
  double& r = x;

  std::cout << sizeof(x) << std::endl;
  std::cout << sizeof(p) << std::endl;
  std::cout << sizeof(r) << std::endl;

  std::cout << x << std::endl;
  std::cout << &x << std::endl;
  std::cout << p << std::endl;
  std::cout << *p << std::endl;
  std::cout << &p << std::endl;
  std::cout << r << std::endl;
  std::cout << &r << std::endl;

  reference::S s;
  reference::S& rs = s;

  std::cout << sizeof(s) << std::endl;
  std::cout << sizeof(rs) << std::endl;
  std::cout << &s << std::endl;
  std::cout << &rs << std::endl;

  return 0;
}

8
8
8

0
0x7fffd7f79b10
0x7fffd7f79b10
0
0x7fffd7f79b08
0
0x7fffd7f79b10

16
16

0x7fffd7f79af8
0x7fffd7f79af8

有句话讲得好,reference就是一种漂亮的pointer

引用的用途

  • 注意const是函数签名的一部分
组合 & 继承 & 委托 中的构造和析构

组合

  • 构造由内而外
Container::Container() : Component() {}
  • 析构由外而内
Container::~Container() { ~Component(); }

注意,编译器只能帮我们调用default构造器,有需要的话需要自己实现

继承

继承+组合关系下的构造和析构

  • 构造由内而外
    子类的构造函数先调用父类的默认构造函数,然后调用组件的默认构造函数,最后才执行自己。
Sub::Sub() : base(), Component() {}
  • 析构由外而内
    子类的析构函数先析构自己,在调用组件的析构函数,最后调用父类的构造函数。
Sub::~Sub() { 
  // Do something;
  ~Component();
  ~base();
}
关于 vptr 和 vtbl
namespace Virtual {
  class A{
  public:
    virtual void vfunc1();
    virtual void vfunc2();
    void func1();
    void func2();

  private:
    int m_data1, m_data2;
  };

  class B : public A{
  public:
    virtual void vfunc1();
    void func2();

  private:
    int m_data3;
  };

  class C : public B{
  public:
    virtual void vfunc1();
    void func2();
  private:
    int m_data_4;
  };
}

(*(p->vptr)[n])(p)

(* p->vptr[n])(p)
静态绑定
call ox.....
动态绑定
  1. 指针调用
  2. 向上转型
  3. 调用的是虚函数
(*(p->vptr)[n])(p)

关于this

this 就是当前对象的地址

看一个例子 这个和上面的虚机制是一脉相承的

class Cdocument {
public:
  virtual Serialize();
};

// 一个应用程序框架
Cdocument::onFileOpen() {
  ...
  Serialize(); // 一个虚函数
  ...
}

// 应用程序
class CMyDoc: public Cdocument {
  virtual Serialize() {
    ...
  }
}

int main() {
  CMyDoc myDoc;
  ...
  myDoc.onFileOpen(); // 调用父类方法
  // 相当于 Cdocument::onFileOpen(&myDoc); this == &myDoc
  // 由于是继承所以在子类中其实有一个父类(调用了构造函数) 
  // Cdocument::onFileOpen(&myDoc) 中 传入的指针是一个向上转型的父类(子->父)
  // 然后执行到Serialize() 时由于是一个成员函数相当于 this->Serialize() == &myDoc->Serialize()
  // 然后相当于 (*(this->vptr)[n])(this) 这个就是动态绑定
  
}


关于动态绑定(看看汇编)
B b;

A a = (A)b;
a.vfunc1(); // 这句是静态绑定

A* pa = new B;
ps->vfunc1();

pa = &b;
pa->vfunc1();

谈谈const
const object(data members 不得变动)non-const object(data members可以变动
const member functions(保证不修改data members)TT
non-const member functions(不保证不修改data members)FT

当成员函数的const和non-const版本同时存在,const object只能调用 const 版本 non-const object只能调用 non-const版本

std::String中的设计

当成员函数的const和non-const版本同时存在,const object只能调用 const 版本 non-const object只能调用 non-const版本

class template std::basic_string<...>中有如下两个member functions:

charT operator[] (size_typr pos) const {
  // 不需要考虑写时复制
}

reference operator[] (size_type pos) {
  // 必须要考虑写时复制
}
关于New Delete

没有虚函数

#include 
#include 
#include 
#include 

class Foo {
public:
  int _id;
  long _data;
  std::string _str;

public:
  Foo() : _id(0) {
    std::cout << "调用default ctor.this=" << this << "id=" << _id << std::endl;
  }
  Foo(int i) : _id(i) {
    std::cout << "调用default ctor.this=" << this << "id=" << _id << std::endl;
  }
  //virtual ~Foo() { std::cout << "调用dtor.this=" << this << "id=" << _id << std::endl; }
  ~Foo() { std::cout << "调用dtor.this=" << this << "id=" << _id << std::endl; }

  static void *operator new(size_t size);
  static void operator delete(void *pdead, size_t size);
  static void *operator new[](size_t size);
  static void operator delete[](void *pdead, size_t size);
};

void *Foo::operator new(size_t size) {
  std::cout << "调用new() size=" << size < 

结果

48
调用new() size=48
先申请内存
调用default ctor.this=0x55ee164252c0id=7
调用dtor.this=0x55ee164252c0id=7
调用delete()
free内存
调用new[]() size=248
先申请内存
调用default ctor.this=0x55ee16425308id=0
调用default ctor.this=0x55ee16425338id=0
调用default ctor.this=0x55ee16425368id=0
调用default ctor.this=0x55ee16425398id=0
调用default ctor.this=0x55ee164253c8id=0
调用dtor.this=0x55ee164253c8id=0
调用dtor.this=0x55ee16425398id=0
调用dtor.this=0x55ee16425368id=0
调用dtor.this=0x55ee16425338id=0
调用dtor.this=0x55ee16425308id=0
调用delete[]()
free内存

有虚函数

#include 
#include 
#include 
#include 

class foo {
public:
  int _id;
  long _data;
  std::string _str;

public:
  foo() : _id(0) {
    std::cout << "调用default ctor.this=" << this << "id=" << _id << std::endl;
  }
  foo(int i) : _id(i) {
    std::cout << "调用default ctor.this=" << this << "id=" << _id << std::endl;
  }
  virtual ~foo() { std::cout << "调用dtor.this=" << this << "id=" << _id << std::endl; }
  //~foo() { std::cout << "调用dtor.this=" << this << "id=" << _id << std::endl; }

  static void *operator new(size_t size);
  static void operator delete(void *pdead, size_t size);
  static void *operator new[](size_t size);
  static void operator delete[](void *pdead, size_t size);
};

void *foo::operator new(size_t size) {
  std::cout << "调用new() size=" << size < 

结果

56
调用new() size=56
先申请内存
调用default ctor.this=0x55d683a2f2c0id=7
调用dtor.this=0x55d683a2f2c0id=7
调用delete()
free内存
调用new[]() size=288
先申请内存
调用default ctor.this=0x55d683a2f308id=0
调用default ctor.this=0x55d683a2f340id=0
调用default ctor.this=0x55d683a2f378id=0
调用default ctor.this=0x55d683a2f3b0id=0
调用default ctor.this=0x55d683a2f3e8id=0
调用dtor.this=0x55d683a2f3e8id=0
调用dtor.this=0x55d683a2f3b0id=0
调用dtor.this=0x55d683a2f378id=0
调用dtor.this=0x55d683a2f340id=0
调用dtor.this=0x55d683a2f308id=0
调用delete[]()
free内存

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/457750.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号