0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C++ 仮想関数について、簡単に実例

Last updated at Posted at 2023-02-06

仮想関数について

毎回、混乱するのでまとめ

何もなし

#include <iostream>

class Base {
public:
  ~Base() {
    std::cout << "Base destructor" << std::endl;
  }
};

class Derived : public Base {
public:
  ~Derived() {
    std::cout << "Derived destructor" << std::endl;
  }
};

int main() {
  Base *b = new Derived;
  delete b;
  return 0;
}
❯ clang++ -Wall -Wextra -Werror test.cpp && ./a.out
Base destructor

親クラスのデストラクタが呼ばれる

親クラスにvirtualあり

#include <iostream>

class Base {
public:
  virtual ~Base() {
    std::cout << "Base destructor" << std::endl;
  }
};

class Derived : public Base {
public:
  ~Derived() {
    std::cout << "Derived destructor" << std::endl;
  }
};

int main() {
  Base *b = new Derived;
  delete b;
  return 0;
}
❯ clang++ -Wall -Wextra -Werror test.cpp && ./a.out
Derived destructor
Base destructor

両方にvirtual

#include <iostream>

class Base {
public:
  virtual ~Base() {
    std::cout << "Base destructor" << std::endl;
  }
};

class Derived : public Base {
public:
  virtual ~Derived() {
    std::cout << "Derived destructor" << std::endl;
  }
};

int main() {
  Base *b = new Derived;
  delete b;
  return 0;
}
❯ clang++ -Wall -Wextra -Werror test.cpp && ./a.out
Derived destructor
Base destructor

小クラスのみにvirtual

こんなの普通はしないけど

#include <iostream>

class Base {
public:
  ~Base() {
    std::cout << "Base destructor" << std::endl;
  }
};

class Derived : public Base {
public:
  virtual ~Derived() {
    std::cout << "Derived destructor" << std::endl;
  }
};

int main() {
  Base *b = new Derived;
  delete b;
  return 0;
}
❯ clang++ -Wall -Wextra -Werror test.cpp && ./a.out
Base destructor

孫クラスありだと

当たり前ですね。

#include <iostream>

class Base {
public:
  ~Base() {
    std::cout << "Base destructor" << std::endl;
  }
};

class Derived : public Base {
public:
  virtual ~Derived() {
    std::cout << "Derived destructor" << std::endl;
  }
};

class Derived2 : public Derived {
public:
  virtual ~Derived2() {
    std::cout << "Derived2 destructor" << std::endl;
  }  
};

int main() {
  Base *b = new Derived2;
  delete b;
  return 0;
}
❯ clang++ -Wall -Wextra -Werror test.cpp && ./a.out
Base destructor

まとめ(追記)

コメントに頂いたことを踏まえ自分でいろいろ試してみました。

アセンブリを見たり、sizeofでコンパイルされたクラスのサイズを比較したりすると、生成されるアセンブリは変更されるし、クラスのサイズ自体も増えるので、明確に使用されるとわかっているタイミングでしか、virtualをつけないほうがいいと結論しました。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?