読者です 読者をやめる 読者になる 読者になる

ゆとりーなの日記

日記的な事を書いて行くと思はれる

多態の話

多態を実現しようとしてこんなコードを書く人ってほんとにいるんですか?って話です。

#include <iostream>

struct triangle {
  void draw() {
    std::cout << "三角形です!" << std::endl;
  }
};

struct rectangle {
  void draw() {
    std::cout << "四角形です!" << std::endl;
  }
};

struct circle {
  void draw() {
    std::cout << "円です!" << std::endl;
  }
};

enum shape_type {kIsTriangle, kIsRectangle, kIsCircle};

struct shape {
  shape_type type;
  void *object;
};

const int kShapeMaxCount = 3;

int main() {
  shape s[kShapeMaxCount] = {
    {kIsTriangle, new triangle()}, {kIsRectangle, new rectangle()}, {kIsCircle, new circle()}
  };
  for (int i = 0; i < kShapeMaxCount; ++i) {
    switch (s[i].type) {
      case kIsTriangle:
        ((triangle *)(s[i].object))->draw();
        break;
      case kIsRectangle:
        ((rectangle *)(s[i].object))->draw();
        break;
      case kIsCircle:
        ((circle *)(s[i].object))->draw();
        break;
    }
  }
  for (int i = 0; i < kShapeMaxCount; ++i) {
    switch (s[i].type) {
      case kIsTriangle:
        delete ((triangle *)(s[i].object));
        break;
      case kIsRectangle:
        delete ((rectangle *)(s[i].object));
        break;
      case kIsCircle:
        delete ((circle *)(s[i].object));
        break;
    }
  }
  return 0;
}

まぁ流石にこれはC++的には論外でしょう。風の噂によるとちょっと賢いCプラーはRTTIの存在を知っているのでこのコードを次のように書くかもしれませんとのことです。

#include <iostream>

struct shape {
  virtual ~shape() {}
};

struct triangle : public shape {
  void draw() {
    std::cout << "三角形です!" << std::endl;
  }
};

struct rectangle : public shape {
  void draw() {
    std::cout << "四角形です!" << std::endl;
  }
};

struct circle : public shape {
  void draw() {
    std::cout << "円です!" << std::endl;
  }
};

const int kShapeMaxCount = 3;

int main() {
  shape *s[kShapeMaxCount] = {
    new triangle(), new rectangle(), new circle()
  };
  for (int i = 0; i < kShapeMaxCount; ++i) {
    triangle *t;
    rectangle *r;
    circle *c;
    if (t = dynamic_cast<triangle *>(s[i])) {
      t->draw();
    } else if (r = dynamic_cast<rectangle *>(s[i])) {
      r->draw();
    } else if (c = dynamic_cast<circle *>(s[i])) {
      c->draw();
    }
  }
  for (int i = 0; i < kShapeMaxCount; ++i) {
    delete s[i];
  }
  return 0;
}

いや、流石にdynamic_castで分岐するってコードを閃く人はいないでしょう。というかよっぽど変な勉強しない限りRTTIをポリモーフィズムよりも先に知ってしまう人の方が稀です。多分。