개발개발/c++
c++의 순수가상함수, 오버라이드, 다중상속, final, 생성자에서 initialize
유잉유잉유잉
2024. 12. 16. 10:16
728x90
▶️ 순수가상함수
- 부모클래스의 함수를 자식 클래스에서 반드시 재정의하도록 명시하는 함수입니다.
- 자식 클래스에서 순수가상함수가 선언되지 않으면 에러가 납니다.
- 부모클래스에서 순수 가상함수에 구현부를 만들 수 있습니다 (안만들어도 됩니다)
// A.h
class A
{
// 일반 가상함수 선언
// 자식함수에서 재정의 하지 않아도 사용가능
virtual void Pure();
// 순수가상함수 선언
virtual void Test() = 0;
virtual void Test2() abstract ;
}
class B : public A
{
virtaul void Test();
virtual void Test2();
}
class C : public A
{
virtual void Pure();
virtual void Test();
}
class main()
{
// 가능
B * b = new B ;
// 에러 : Test2()를 재정의하지 않아서 사용할 수가 없음
C * c = new C; //[에러] 추상 클래스 형식 "C"의 개체를 사용할 수 없습니다.
return 0;
}
▶️ 순수가상함수 선언방법 두가지
- 함수명 뒤에 0을 넣기
- 함수명 뒤에 abstract 키워드 붙이기
▶️추상클래스
- 객체 생성할 필요 없을 경우 선언하여 사용합니다
- 순수가상함수를 하나라도 가지고 있는 클래스를 추상클래스라고 합니다.
- 순수가상함수는 자식 클래스에서 반드시 재정의 해야합니다.
- 자식클래스에서 순수가상함수가 재정의가 안될 경우, 자식 클래스 또한 추상클래스로 취급됩니다.
- 추상 클래스 선언방법 : 클래스명 뒤에 abstract 키워드 추가
class A abstract
{
}
void main()
{
// 추상 클래스라서 객체 생성 불가
A * a = new A;
}
▶️ override
- override 키워드는 이 함수가 부모의 함수를 재정의한 함수임을 명시합니다.
- 만약 부모 클래스의 함수들 중 같은 형태의 함수가 없다면 이 함수는 에러를 발생시킵니다
- 함수를 재정의하며 생기는 에러를 줄여줍니다.
// A.h
class A abstract
{
public :
virtual void Test();
virtual void Test2(int num);
}
// B.h
#include "A.h"
class B : public A
{
public :
virtual void Test() override ;
virtual void Test2(int num, int num) override ; // 에러. 부모의 함수 형태와 다름
}
▶️ 다중상속
여러 부모를 상속받는 기능입니다.
class A
{
}
class B
{
}
// class C는 A와 B를 둘 다 상속받습니다.
class C :
public A, public B
{
}
▶️ 다중상속 주의점
변수명이나 함수명이 겹치면 문제가 생길 수 있으니 주의해서 사용하세요
class A
{
public :
int num;
int num2;
float num3;
}
class B
{
public :
int num;
char ch;
;
class C
: public A, public B
{
}
void main()
{
C * c = new C;
c->num ;// A의 num인지 B의 num인지 확인이 어려움
}
▶️ Final
- 함수에서 사용
- 해당 클래스를 상속받은 자식 클래스에서 더이상 재정의 할 수 없게 명시적으로 표현합니다.
- 함수명 뒤에 final을 붙여서 선언합니다
class A
{
public :
void Output() final ;
}
class B : public A
{
public :
void Output() ; // [에러] final 함수 재정의 불가
}
- 클래스에서 사용 :
- 상속을 받을 수 없는 클래스로 만들어줍니다. ( 부모클래스로 사용할 수 없습니다 )
- 클래스 명 뒤에 final 키워드를 붙여서 선언해줍니다.
class A final
{
}
class B
: public A // 상속불가
{
}
▶️ 자식 생성자에서 부모 생성자함수 먼저 호출하기
// A.h
class A
{
public :
A();
A( const A& obj );
~A();
public :
virtual A* Clone();
}
// A.cpp
A::A(){}
// 인자로 들어오는 오브젝트를 대입하여 모든 멤버변수를 얕은복사로 복사하기
A::A( const A& obj )
{
*this = obj;
}
// B.h
class B
: public A
{
public :
B();
B( const B& obj);
~B();
public :
virtual B* Clone();
}
// B.cpp
B::B(){}
B::B(const B& obj ) : A(obj) // <--------------
{
}
B* B::Clone()
{
new B(*this);
}
▶️ 매크로
- 매크로는 디버깅이 되지 않기 때문에 디버깅이 필요없는곳에서만 사용하길 권장합니다.
- 한줄로 써야하지만 한 줄이 넘어갈 경우 문장 맨 끝 마지막마다 (\)를 붙여줍니다
- \뒤에 공백등 문자가 들어갈 경우 에러가 발생합니다.. (^^...)
- 장문의 맨 마지막 문장엔 \를 안붙여야 합니다
- ex: 싱글턴패턴, 메모리 제거 매크로 등
// GameInfo.h
#include <iostream>
#define SAFE_DELETE(p) { delete p; p = nullptr; }
#define DECLARE_SINGLE(type) \
private : \
type(); \
~type(); \
private : \
static type * mInst; \
public : \
static type * GetInst() \
{ \
if( nullptr == mInst ) \
mInst = new type ; \
return mInst; \
} \
static void DestroyInst() \
{ SAFE_DELETE( mInst ); }
#define DEFINITION_SINGLE(Type) type* type::mInst = nullptr;
▶️ 생성자에서 변수 초기화하기
class A
{
public :
A() : num(0), option(0)
public :
int num = 0;
int option = 0;
}
class B : public A
{
public :
B() : num(0) // ----> 에러 부모 클래스의 변수는 생성자에서 이니셜라이징 불가능하다
{
num = 0; // 이런식으로 해야함
}
public :
int buy = 0;
}
728x90