반응형
오늘 공부한 내용📓
- C++
개념 공부
Orthodox Canonical Form
- OCCF 란, 클래스의 기본적인 형식 또는 일반적인 형식을 따르는 규칙 집합
- 이 규칙들은 클래스의 일관성과 호환성을 유지하고, 예기치 않은 동작을 방지하는데 도움을 줌
- C++ 98 버전의 OCCF 는 아래 규칙을 포함함
- 기본 생성자(Default Constructor)
- 복사 생성자(Copy Constructor)
- 소멸자(Destructor)
- 대입 연산자(Assignment Operator)
- 동등 연산자(Equality Operator)
- 복사 할당 연산자(Copy Assignment Operator)
- ostream 연산자(’<<’) 오버로딩
- istream 연산자(’>>’) 오버로딩
- 42 과제에서는 위 규칙들 중 기본 생성자, 복사 생성자, 복사 할당 연산자, 소멸자만을 필수로 요구함
오버로딩(Overloading)
- 같은 이름을 가진 함수나 연산자가 다양한 매개변수로 다른 동작을 수행할 수 있도록 하는 기능
- 동일한 이름의 함수나 연산자를 여러번 정의할 수 있고, 함수나 연산자 호출 시에 전달되는 인자의 유형이나 개수에 따라 적절한 함수나 연산자가 선택됨
- 오버로딩은 함수 오버로딩과 연산자 오버로딩으로 나뉨
- 함수 오버로딩
- 동일한 이름을 가진 함수가 서로 다른 매개변수 목록을 가지도록 허용하는 기능
- 함수의 이름을 재사용하며, 비슷한 동작을 하는 여러 함수를 구현하는데 유용함
- int add(int a, int b) { return a + b; } int add(double a, double b) { return a + b; } int main() { add(1,2); //int add(int a, int b) 함수가 호출됨 add(1.1, 2.2); //int add(double a, double b) 함수가 호출됨 return 0; }
- 연산자 오버로딩
- C++에서 기본적으로 제공되는 연산자(+,-,* 등)에 대해 사용자가 동작을 정의할 수 있게 하는 기능
- 클래스나 구조체에 대해 기존 연산자를 재정의하여 원하는 동작을 수행할 수 있음
- class Vector { private: double x, y; public: Vector(double x, double y) : x(x), y(y) {} Vector operator+(const Vector& other) const { return Vector(x + other.x, y + other.y); } }
- 함수 오버로딩
복사 생성자(Copy Constructor)
- 다른 객체의 값을 복사하여 새로운 객체를 생성하며, 일반적으로 참조로 전달
- 복사생성자는 기본적으로 c++ 컴파일러에서 제공되며, 사용자가 별도로 정의하지 않아도 자동으로 생성됨. 디폴트 복사 생성자는 얕은 복사를 함.
- MyClass obj1; //MyClass 의 객체 obj1을 생성 MyClass obj2(obj1); //obj1을 사용하여 obj2를 복사 생성자 호출
- 복사 생성자는 기존 값을 복사해 전달하는 개념이기 때문에, 값이 변경되지 않도록 const 로 선언한다.
- class MyClass { publick: MyClass(const MyClass& other){ //객체 복사 } }
- 얕은 복사(Shallow Copy)란?
- 단순히 원본 객체의 주소를 복사 대상 객체에 할당하는 것
- 원본 객체와 복사된 객체는 동일한 메모리를 공유함
- class MyClass { public: int* data; MyClass(const MyClass& other) { // 주소만 복사되고 데이터는 공유됨 data = other.data; } };
- 깊은 복사(Deep Copy)란?
- 복사 대상 객체에 새로 메모리를 할당하여 데이터를 복사하는 것
- 원본 객체와 복사된 객체가 다른 메모리를 갖기 때문에, 변경이 발생해도 서로 영향을 주지 않음
- 복사 생성자나 대입 연산자 오버로딩을 통해 수행될 수 있음
- class MyClass { public: int* data; MyClass(const MyClass& other) { // 새로운 메모리를 할당하고 데이터를 복사함 data = new int(*other.data); } ~MyClass() { delete data; // 메모리 해제 } };
대입 연산자(Assignment Operator)
class MyClass {
public:
// 대입 연산자 오버로딩
MyClass& operator=(const MyClass& other) {
// 대입 연산자의 본문에는 객체를 복사하는 로직이 들어감
// 다른 멤버 변수들을 다른 객체에서 복사하여 할당하는 등의 작업을 수행할 수 있음
if (this != &other) { // 자기 자신에게 대입하는지 확인
// 멤버 변수 복사
}
return *this; // 대입 후 자기 자신을 반환
}
};
- 클래스의 객체에 다른 객체의 값을 할당하는 연산자(’=’)
- 클래스의 멤버 변수를 다른 객체의 멤버 변수로 복사하여, 객체 간의 데이터를 교환하거나 복사할 때 주로 사용됨
- 복사 개념이기 때문에 얕은 복사와 깊은 복사의 개념이 적용됨
동등 연산자(Equality Operator)
- 두 개의 값을 비교하고, 동일한 값이면 true를, 다른 값이면 false 를 반환하는 연산자(’==’)
- 기본 데이터 유형(정수, 실수 등) 뿐만 아니라 사용자가 정의한 클래스나 구조체에 대해서도 사용할 수 있음. 이 경우에는 동등 연산자 오버로딩을 통해 사용자가 직접 판단하는 방식을 정의해야 함
class Person
{
private:
std::string name;
int age;
public:
Person(const std::string& name, int age) : name(name), age(age) {}
bool operator==(const Person& other) const
{
return (name == other.name && age == other.age);
}
}
복사 할당 연산자(Copy Assignment Operator)
class MyString
{
private:
char *buffer;
public:
MyString(const char *str)
{
int len = 0;
while (str[len] != '\\0')
len++;
buffer = new char[len + 1];
for (int i = 0; i < len; i++)
buffer[i] = str[i];
buffer[len] = '\\0';
}
MyString& operator=(const MyStyle& other) //복사 할당 연산자
{
if (this == &other) // 자기 자신인지 확인
return *this;
delete[] buffer; // 기존 할당된 메모리 해제
int len = 0;
while (str[len] != '\\0')
len++;
buffer = new char[len + 1]; // 새 메모리 할당
for (int i = 0; i < len; i++)
buffer[i] = other.buffer[i]; // 값 복사
buffer[len] = '\\0';
return *this;
}
}
- 이미 생성된 객체에 대해 다른 객체의 값을 할당하거나, 이미 할당된 메모리 자원을 해제하고 다른 값으로 다시 할당할 때 사용하는 연산자(’=’)
- 일반적으로 반환 형식은 ‘클래스명&’ 이며, 매개변수는 ‘const 클래스명&’
- 복사 생성자와의 차이점은 호출되는 시점과 사용되는 상황에 차이가 있음.
- 복사 생성자 : 객체가 생성될 때, 복사 생성자를 호출하는 경우. 새로운 객체에 대해 기존 객체의 값으로 초기화 하기 위해 사용
- 복사 할당 연산자 : 객체가 이미 생성된 후. 다른 객체의 값으로 할당하여 복사 하기 위해 사용
ostream 연산자(’<<’) 오버로딩
class Person
{
private:
std::string name;
int age;
public:
Person(const std::string& name, int age) : name(name), age(age) {}
std::ostream& print(std::ostream& os) const
{
os << name << age;
return os;
}
}
// ostream 연산자 오버로딩
std::ostream& poerator<<(std::ostream& os, const Person& person)
{
return person.print(os);
}
- ‘<<’ 연산자는 std::ostream 객체에 대한 출력을 수행하는 연산자로, ‘<<’ 연산자를 오버로딩하여 사용자가 정의한 클래스나 구조체에 대한 출력 동작을 지정할 수 있음
- 반환 형식은 출력 스트림 객체를 참조 형식(std::ostream&)으로 반환하고, 매개변수를 출력 스트림 객체(std::ostream&)와 출력하고자 하는 사용자 정의 클래스(또는 구조체) 객체를 받음
istream 연산자(’>>’) 오버로딩
class Person
{
private:
std::string name;
int age;
public:
Person() {}
std::istream& read(std::istream& is)
{
is >> name >> age;
return is;
}
}
std::istream& operator>>(std::istream& is, Person& person)
{
return person.read(is);
}
- ‘>>’ 연산자는 std::istream 객체에서 입력을 수행하는 연산자로, ‘>>’ 연산자를 오버로딩하여 사용자가 정의한 클래스나 구조체에 대한 입력 동작을 지정할 수 있음
- 반환 형식은 입력 스트림 객체를 참조 형식(std::istream&)으로 반환하고, 매개변수를 입력 스트림 객체(std::istream&)와 입력받고자 하는 사용자 정의 클래스(또는 구조체) 객체를 받음
제가 공부한 내용을 기록하고 있습니다.
혹시 수정이 필요한 부분이 있다면, 댓글로 지적 부탁드립니다!
선한 관심과 도움 감사드립니다😊
반응형
'TIL::Today I Learn' 카테고리의 다른 글
[TIL] 2023714 (1) | 2023.07.18 |
---|---|
[TIL] 20230708 (0) | 2023.07.18 |
[TIL] 20230705 (0) | 2023.07.06 |
[TIL] 20230704 (0) | 2023.07.06 |
[TIL] 20230622 (0) | 2023.06.24 |