C++スコーラ
仮想関数
最終更新:
Bot(ページ名リンク)
-
view
仮想関数
仮想関数
スーパークラス側の関数の前に「virtual」とつけることによって、前章の問題は解決します。
前に「virtual」とついた関数のことを仮想関数と呼びます。
仮想関数をオーバーライドした場合、派生クラスの関数が優先されて呼び出されます。
前に「virtual」とついた関数のことを仮想関数と呼びます。
仮想関数をオーバーライドした場合、派生クラスの関数が優先されて呼び出されます。
/*--------------Person.hの中身----------------*/ #pragma once #include < string > using namespace std; class Person{ protected: string name; // 名前 int age; // 年齢 public: Person(string name, int age); // コンストラクタ virtual ~Person(); // デストラクタ virtual void SelfIntroduction(); // 自己紹介(仮想関数) };
/*--------------Student.hの中身----------------*/ #pragma once #include "Person.h" class Student : public Person { protected: int id; // 学籍番号 public: Student(string name, int age, int id); // コンストラクタ ~Student(); // デストラクタ void SelfIntroduction() // 自己紹介([[オーバーライド]]) int GetID(); // 学籍番号のゲッター }; /*--------------main.cppの中身----------------*/ #include "Student.h" int main(){ Person *satou = new Person("佐藤", 69); // Person[[クラス]] Student *suzuki = new Student("鈴木", 24, 241035); // Student[[クラス]] satou->SelfIntroduction(); // 自己紹介(Person) suzuki->SelfIntroduction(); // 自己紹介(Student) delete satou; delete suzuki; return 0; }
純粋仮想関数
仮想関数は何かしらの定義を持ちましたが、
定義を持たない仮想関数を作ることもできます。
これを純粋仮想関数と呼び、以下のように = 0 をつけることで実現します。
定義を持たない仮想関数を作ることもできます。
これを純粋仮想関数と呼び、以下のように = 0 をつけることで実現します。
virtual void SelfIntroduction() = 0;
上のように書くことで定義がないことを表しています。
オーバーライドしなければ使えません。
オーバーライドしなければ使えません。
Person *satou = new Person("佐藤", 69); // Person[[クラス]]【エラー】
必ず継承し、関数を再定義して使うのです。
機能の宣言のみを持ったインターフェースですが、どのようなメリットがあるかつかみにくいと思います。
多態性の章において、基底クラスのポインタには、その派生クラスであればどんなオブジェクトでも扱うことができると書きました。
インターフェースはクラス階層の土台に位置し、抽象的な宣言のみ行います。
クラス使用者はインターフェースのみ知っていれば機能を使うことができる上
インターフェースから派生した様々なオブジェクトを同じコードで処理することができます。
多態性の章において、基底クラスのポインタには、その派生クラスであればどんなオブジェクトでも扱うことができると書きました。
インターフェースはクラス階層の土台に位置し、抽象的な宣言のみ行います。
クラス使用者はインターフェースのみ知っていれば機能を使うことができる上
インターフェースから派生した様々なオブジェクトを同じコードで処理することができます。
例
/*--------------Shape.hの中身----------------*/ #pragma once class Shape{ public: Shape(); virtual ~Shape(); virtual double getArea() = 0; };
/*--------------Shape.cppの中身----------------*/ #include "Shape.h" Shape::Shape(){ } Shape::~Shape(){ }
/*--------------Rect.hの中身----------------*/ #pragma once #include "shape.h" class Rect : public Shape { private: double width; double height; public: Rect(double width, double height); ~Rect(); double getArea(); };
/*--------------Rect.cppの中身----------------*/ #include "Rect.h" Rect::Rect(double width, double height){ this->width = width; this->height = height; } Rect::~Rect(){ } double Rect::getArea(){ return this->height * this->width; }
/*--------------Circle.hの中身----------------*/ #pragma once #include "shape.h" class Circle : public Shape { private: double radius; public: Circle(double radius); ~Circle(); double getArea(); };
/*--------------Circle.cppの中身----------------*/ #include "Circle.h" // M_PIを使うのに必要 #define _USE_MATH_DEFINES #include <Math.h> Circle::Circle(double radius) { this->radius = radius; } Circle::~Circle(){ } double Circle::getArea(){ return this->radius * this->radius * M_PI; }
/*--------------main.cppの中身----------------*/ #include < iostream > #include "Rect.h" #include "Circle.h" using namespace std; int main() { Shape* sikaku = new Rect(20, 30); // 四角 Shape* maru = new Circle(20); // 円 cout << "四角:" << sikaku->getArea() << endl; cout << "円 :" << maru->getArea() << endl; delete sikaku; delete maru; return 0; }