developer tip

C ++ 가상 함수를 안전하게 재정의

optionbox 2020. 8. 22. 08:39
반응형

C ++ 가상 함수를 안전하게 재정의


가상 함수가있는 기본 클래스가 있고 파생 클래스에서 해당 함수를 재정의하고 싶습니다. 파생 클래스에서 선언 한 함수가 실제로 기본 클래스의 함수를 재정의하는지 컴파일러에서 확인하는 방법이 있습니까? 이전 함수를 재정의하는 대신 실수로 새 함수를 선언하지 않았는지 확인하는 매크로 또는 무언가를 추가하고 싶습니다.

이 예를 보자 :

class parent {
public:
  virtual void handle_event(int something) const {
    // boring default code
  }
};

class child : public parent {
public:
  virtual void handle_event(int something) {
    // new exciting code
  }
};

int main() {
  parent *p = new child();
  p->handle_event(1);
}

자식의 메서드가 선언을 놓치고 새 메서드를 선언 하기 때문에 parent::handle_event()대신 여기 가 호출됩니다 . 이것은 함수 이름의 오타이거나 매개 변수 유형의 사소한 차이 일 수도 있습니다. 기본 클래스의 인터페이스가 변경되고 일부 파생 클래스가 변경 사항을 반영하도록 업데이트되지 않은 경우에도 쉽게 발생할 수 있습니다.child::handle_event()const

이 문제를 피할 수있는 방법이 있습니까? 어떻게 든 컴파일러 나 다른 도구에 이것을 확인하도록 지시 할 수 있습니까? 유용한 컴파일러 플래그 (g ++ 권장)가 있습니까? 이러한 문제를 어떻게 피할 수 있습니까?


g ++ 4.7부터는 새로운 C ++ 11 override키워드를 이해합니다 .

class child : public parent {
    public:
      // force handle_event to override a existing function in parent
      // error out if the function with the correct signature does not exist
      void handle_event(int something) override;
};

C #의 override키워드 와 같은 것은 C ++의 일부가 아닙니다.

gcc에서 -Woverloaded-virtual이름은 같지만 서명이 충분히 다른 기본 클래스 가상 함수를 숨기지 않도록 경고합니다. 그러나 함수 이름 자체의 철자를 잘못 입력하여 함수를 재정의하는 데 실패하지 않도록 보호하지는 않습니다.


내가 아는 한, 추상적으로 만들 수 없나요?

class parent {
public:
  virtual void handle_event(int something) const = 0 {
    // boring default code
  }
};

I thought I read on www.parashift.com that you can actually implement an abstract method. Which makes sense to me personally, the only thing it does is force subclasses to implement it, no one said anything about it not being allowed to have an implementation itself.


In MSVC, you can use the CLR override keyword even if you're not compiling for CLR.

In g++, there's no direct way of enforcing that in all cases; other people have given good answers on how to catch signature differences using -Woverloaded-virtual. In a future version, someone might add syntax like __attribute__ ((override)) or the equivalent using the C++0x syntax.


In MSVC++ you can use keyword override

class child : public parent {
public:
  virtual void handle_event(int something) <b>override</b> {
    // new exciting code
  }
};

override works both for native and CLR code in MSVC++.


Make the function abstract, so that derived classes have no other choice than to override it.

@Ray Your code is invalid.

class parent {
public:
  virtual void handle_event(int something) const = 0 {
    // boring default code
  }
};

Abstract functions cannot have bodies defined inline. It must be modified to become

class parent {
public:
  virtual void handle_event(int something) const = 0;
};

void parent::handle_event( int something ) { /* do w/e you want here. */ }

I would suggest a slight change in your logic. It may or may not work, depending on what you need to accomplish.

handle_event() can still do the "boring default code" but instead of being virtual, at the point where you want it to do the "new exciting code" have the base class call an abstract method (i.e. must-be-overridden) method that will be supplied by your descendant class.

EDIT: And if you later decide that some of your descendant classes do not need to provide "new exciting code" then you can change the abstract to virtual and supply an empty base class implementation of that "inserted" functionality.


Your compiler may have a warning that it can generate if a base class function becomes hidden. If it does, enable it. That will catch const clashes and differences in parameter lists. Unfortunately this won't uncover a spelling error.

For example, this is warning C4263 in Microsoft Visual C++.


C++11 override keyword when used with the function declaration inside the derived class, it forces the compiler to check that the declared function is actually overriding some base class function. Otherwise, the compiler will throw an error.

Hence you can use override specifier to ensure dynamic polymorphism (function overriding).

class derived: public base{
public:
  virtual void func_name(int var_name) override {
    // statement
  }
};

참고URL : https://stackoverflow.com/questions/497630/safely-override-c-virtual-functions

반응형