오늘은 클래스 복습, 연산자 오버로딩 전위 증가, 후위 증가, 상속의 이론에 대한 수업을 들었다.
1. 클래스 복습
1.1 빈 클래스
#pragma once
class C_DATA
{
public:
C_DATA() = default; // 유니폼 초기화를 사용하겠다
~C_DATA() = default;
C_DATA(const C_DATA&) = default; // call by value를 지원하지 않겠다
//void operator=(C_DATA);
C_DATA& operator=(const C_DATA&) = default; // 대입연산자의 복사를 지원하지 않겠다
};
public이란 인터페이스가 제공된 상태이며
클래스의 멤버로 제공된 기본 생성자와 소멸자는 컴파일러가 자동으로 생성해 주지만 복사 생성자를 명시적으로 삭제하려고 하면 기본 생성자가 자동으로 삭제가 되어버린다. 그렇기에 복사 생성자를 직접 명시할 때, 기본 생성자 ( 생성자, 소멸자)도 명시를 해줘야 한다.
대입 연산자를 삭제를 한다고 하면 void operator=(C_DATA)라고 해도 오류를 잡는다는 상관이 없을 것이다.
하지만 저 코드는 call by value이며 모든 오퍼레이터를 구현할 때는 기존의 기능과 동일하게 구현을 해야 하는 원칙이 존재한다. 그렇기에 모든 기능이 동일한 C_DATA& operator=(const C_DATA&) = default;라고 작성을 해줘야 한다.
- 중요 사항: 클래스의 객체를 call by value로 넘기는 것은 절대 하며 안된다.
2. 연산자 오버로딩 전위, 후위 증가
2.1 전위 증가 (++nData)
- 전위 증가는 자기 자신을 먼저 증가시킨 후, 증가된 자기 자신을 반환한다. 즉, 호출한 쪽에서 증가된 값을 참조하게 된다.
- 예를 들어, ++++++++nData;와 같은 연속적인 전위 증가 코드도 가능하며, 모든 증가 연산이 적용된다.
printf("%d, %d, %d\n", ++nData, ++nData, ++nData);
위 코드는 nData가 10일 때 11로 증가한 후 레퍼런스를 통해 자기 자신을 남기므로, 다시 증가가 반복되어 결과는 모두 13이 된다. ( 래퍼런스의 성질과 동일 )
2.2 후위 증가 (nData++)
- 후위 증가는 현재 값을 먼저 반환한 후 값을 증가시킨다.
- 후위 증가 시 반한 되는 값은 증가되기 전의 값을 call by value로 전달해야 하므로, 증가 후의 결과는 이전 값과 무관하게 자기 자신을 반환하지 않는다.
nData++++++++
후위 증가의 경우 클래스 상수이기 때문에 이런 식의 코드는 오류가 발생한다.
하지만 되는 경우가 존재한다.
C_DATA c;
c++++++;
printf("%d\n", c.getData());
이런 식으로 작성하게 되면 오류가 발생하지 않고 실행이 되기 때문에 const를 붙여 막아줘야 한다.
2.3 구현
잘 보면 전위 증가와 후위 증가를 구별하는 방법이 존재한다.
C_DATA& operator++();
const C_DATA operator++(int);
기본적으로 operator++만 보고는 전위 증가, 후위 증가를 구별할 수는 없다.
그렇기에 구별하기 위해서 후위 증가에 (int)를 붙이게 된다.
즉, operator++(int)는 후위 증가를 나타내기 위해 int를 구별용으로 사용하는 것이며, 실제 값을 넘기지 않는다.
[header.h]
#pragma once
class C_DATA
{
private:
int m_nData;
public:
C_DATA() = default;
void setData(int nData);
int getData();
C_DATA& operator++();
const C_DATA operator++(int); // int를 입력받은게 아니라 int라는 공간이 있으면 후위증가를 뜻함 즉, 구별하기 위해서 존재하는 것
};
[header.cpp]
#include "data.h"
void C_DATA::setData(int nData)
{
m_nData = nData;
}
int C_DATA::getData()
{
return m_nData;
}
C_DATA& C_DATA::operator++()
{
m_nData++;
return *this;
}
const C_DATA C_DATA::operator++(int)
{
C_DATA c;
c.m_nData = m_nData;
m_nData++;
return c;
}
[main.cpp]
#include <iostream>
#include "data.h"
int main()
{
C_DATA c1{};
c1++;
printf("%d\n", c1.getData());
}
주의 : 오퍼레이터는 애초에 클래스에 밀어 넣지 않는다. ( 서로 간의 상호작용이 이루어지지 않기 때문이다 / 사용자가 알아볼 방법이 없음)
3. 상속의 이론
3.1 정의
- 상속은 기존 클래스의 기능을 수정하지 않고 확장함으로써 클래스 간의 계층 구조를 생성하는 메커니즘이다.
- 상속을 통해 여러 객체를 그룹화하거나 확장할 수 있으며, 확장의 개념으로 이해할 수 있다.
즉, 상속은 하나의 자료형에 여러 개의 객체를 묶어서 관리하기 위해 하는 것이라 봐도 무방하다 ( 확장의 개념 )
3.2 상속의 원칙
- 추상화와 구체화의 관계를 만족해야 한다. 즉, 부모 클래스의 이름으로 자식 클래스를 지칭할 수 있어야 하며,
상위 개념( 예 : 대중교통 )이 하위 개념 ( 예 : 버스 )으로 자연스럽게 묶일 수 있어야 한다. - 상속을 받게 되면 추상화하는 객체가 증가하게 되면서 클래스의 객수는 증가하게 된다. 그렇기에 그 견적을 보고 자신이 증가하는 클래스를 커버 가능하다면 하는 것이며 안될 거 같으면 안 하면 되는 것이다.
즉, 자신이 판단으로 상속을 받을지 안 받을지가 정해진다.
'C++' 카테고리의 다른 글
[강의] 11월 8일 수업정리 (1) | 2024.11.10 |
---|---|
[강의] 11월 7일 수업정리 (1) | 2024.11.08 |
[강의] 11월 5일 수업정리 (3) | 2024.11.05 |
[강의] 11월 1일 수업정리 (0) | 2024.11.03 |
[강의] 10월 31일 수업정리 (2) | 2024.11.01 |