
공부한 유튜브 사이트:
[하루10분|C++] 0-1. C++을 학습하여야 하는 이유
&를 붙이면 참조 변수가 됨.#include <iostream>
using namespace std;
int main() {
int a = 10;
int& ref = a; // ref는 a의 참조 (별명)
cout << "a: " << a << ", ref: " << ref << endl;
ref = 20; // ref를 변경하면 a도 변경됨
cout << "a: " << a << ", ref: " << ref << endl;
return 0;
}
/* 출력결과
a: 10, ref: 10
a: 20, ref: 20
class 클래스이름 {
private: // 비공개 멤버 (외부 접근 불가)
데이터_타입 멤버변수;
public: // 공개 멤버 (외부 접근 가능)
반환형 함수이름(매개변수) {
// 함수의 구현
}
};
public | 어디서든 접근 가능 (외부에서도 접근 가능) |
|---|---|
private | 클래스 내부에서만 접근 가능 (기본값) |
protected | private과 비슷하지만 상속받은 클래스에서도 접근 가능 |
#include <iostream>
using namespace std;
class Car { // 클래스 선언
public:
string brand; // 멤버 변수
int speed;
void showInfo() { // 멤버 함수
cout << "브랜드: " << brand << ", 속도: " << speed << "km/h" << endl;
}
};
int main() {
Car myCar; // 객체 생성
myCar.brand = "Hyundai"; // 멤버 변수 값 설정
myCar.speed = 120;
myCar.showInfo(); // 멤버 함수 호출
return 0;
}
class Car {
public:
string brand;
int speed;
**// 매개변수 없는 생성자**
Car() {
brand = "Unknown";
speed = 0;
cout << "자동차 객체가 생성되었습니다." << endl;
}
**// 매개변수가 있는 생성자**
Car(string b, int s) {
brand = b;
speed = s;
}
void showInfo() {
cout << "브랜드: " << brand << ", 속도: " << speed << "km/h" << endl;
}
};
int main() {
Car myCar; **// 생성자 자동 호출**
Car myCar("BMW", 220); **// 매개변수가 있는 생성자 호출**
myCar.showInfo();
return 0;
}
~클래스이름() 형태로 선언.class Car {
public:
Car() { cout << "자동차 객체 생성!" << endl; }
~Car() { cout << "자동차 객체 소멸!" << endl; }
};
int main() {
Car myCar;
return 0;
}
/*출력결과
자동차 객체 생성!
자동차 객체 소멸!
*/
class Car {
private:
int speed;
public:
**void setSpeed(int s); // 함수 선언**
**int getSpeed();**
};
**// 함수 외부 정의**
void Car::setSpeed(int s) { speed = s; }
int Car::getSpeed() { return speed; }
int main() {
Car myCar;
myCar.setSpeed(200);
cout << "현재 속도: " << myCar.getSpeed() << "km/h" << endl;
return 0;
}
//출력: 현재 속도: 200km/h
this는 멤버 함수 내에서만 사용 가능.setBrand(string brand) 함수에서 매개변수와 멤버 변수 이름이 같음.this->brand = brand;에서 this->brand는 객체의 멤버 변수, brand는 매개변수를 의미.this가 없다면 지역 변수와 멤버 변수를 구분할 수 없음.#include <iostream>
using namespace std;
class Car {
private:
string brand;
public:
void setBrand(string brand) {
this->brand = brand; // 멤버 변수와 매개변수 구분
}
void showInfo() {
cout << "브랜드: " << brand << endl;
}
};
int main() {
Car myCar;
myCar.setBrand("Hyundai");
myCar.showInfo();
return 0;
}
//출력: 브랜드: Hyundai
class Car {
private:
string brand;
int speed;
public:
Car* setBrand(string brand) {
this->brand = brand;
**return this; // 자기 자신(객체의 주소) 반환**
}
Car* setSpeed(int speed) {
this->speed = speed;
**return this;**
}
void showInfo() {
cout << "브랜드: " << brand << ", 속도: " << speed << "km/h" << endl;
}
};
int main() {
Car myCar;
myCar.setBrand("BMW")->setSpeed(220)->showInfo();
return 0;
}
//출력: 브랜드: BMW, 속도: 220km/h
#include <iostream>
#include "Stock.cpp"
using namespace std;
int main() {
Stock s[4] = {
Stock("A",10,10000); //s[0]
Stock("A",10,10000); //s[1]
Stock("A", 10, 10000); //s[2]
Stock("A", 10, 10000); //s[3]
}
s[0].show();
return 0;
}
+, -, *, /, == 등)의 기능을 사용자 정의 클래스에 맞게 재정의하는 기능#include <iostream>
class Point {
public:
int x, y;
//생성자, point에 아무값도 안주면 a=b=0으로 설정
Point(int a = 0, int b = 0) : x(a), y(b) {}
// + 연산자 오버로딩
Point operator+(const Point& other) {
return Point(x + other.x, y + other.y);
}
void print() {
std::cout << "(" << x << ", " << y << ")" << std::endl;
};
int main() {
Point p1(2, 3);
Point p2(4, 5);
Point p3 = p1 + p2; // **p1.operator+(p2) 호출**
p3.print(); // (6, 8) 출력
}
//this 포인터를 이용한 연산자 오버로딩
class Car {
private:
string brand;
int speed;
public:
Car(string b, int s) : brand(b), speed(s) {}
**// 대입 연산자 오버로딩**
Car& operator=(const Car& other) {
if (this == &other) return *this; // 자기 자신과의 대입 방지
this->brand = other.brand;
this->speed = other.speed;
return *this; // 자기 자신 반환
}
void showInfo() {
cout << "브랜드: " << brand << ", 속도: " << speed << "km/h" << endl;
}
};
int main() {
Car car1("Audi", 180);
Car car2("Mercedes", 200);
car1 = car2; // 대입 연산자 호출
car1.showInfo();
return 0;
}
friend를 사용하면 특정 함수나 다른 클래스가 해당 클래스의 비공개 멤버에 접근가능#include <iostream>
using namespace std;
class MyClass {
private:
int secret;
public:
MyClass(int s) : secret(s) {}
// friend 함수 선언
friend void showSecret(const MyClass& obj);
};
// friend 함수 정의
void showSecret(const MyClass& obj) {
cout << "Secret: " << obj.secret << endl; **// private 멤버에 접근 가능**
}
int main() {
MyClass obj(42);
showSecret(obj); // friend 함수를 통해 private 멤버 접근 가능
return 0;
}
#include <iostream>
using namespace std;
class A {
private:
int secret;
public:
A(int s) : secret(s) {}
**// B 클래스가 A의 private 멤버에 접근할 수 있도록 허용
friend class B;**
};
class B {
public:
void showSecret(const A& obj) {
cout << "Secret from B: " << obj.secret << endl; // A의 private 멤버 접근 가능
}
};
int main() {
A objA(77);
B objB;
objB.showSecret(objA);
return 0;
}
//출력결과: Secret from B: 77
<< 연산자를 오버로딩하면, cout << 객체; 형태로 객체를 출력이 가능하다
#include <iostream>
using namespace std;
class MyClass {
private:
int data;
public:
MyClass(int d) : data(d) {} // 생성자
// << 연산자 오버로딩을 위해 friend 함수 선언**
friend ostream& operator<<(ostream& os, const MyClass& obj);
};
// << 연산자 오버로딩 함수 정의**
ostream& operator<<(ostream& os, const MyClass& obj) {
os << "MyClass data: " << obj.data; // private 멤버 data에 접근 가능
return os;
}
int main() {
MyClass obj(100);
cout << obj << endl; // << 연산자가 오버로딩되어 있어 가능!
return 0;
}
//출력결과: MyClass data: 100
//상속
//Time에 저장되어있는 것들이 NewTime에 들어감
//NewTime -> 파생클래스형
//NewTime에서 새로운 것들을 추가할 수 있음
class NewTime :public Time {
private:
int day;
public:
NewTime();
NewTime(int, int, int);
void print();
};
//파생클래스는 기초클래스Time의 private요소들에는 직접적으로 접근불가
//-> 해결법은 : Time()
//Time() 생성자의 결과가 NewTime()의 매개변수로 들어감
NewTime::NewTime():Time() {//***
day = 0;
}
NewTime::NewTime(int,int,int) **:Time(h, m)**{
day = d;
}
void NewTime::print() {
std::cout << "일 : " << day << std << endl;
show(); //파생클래스의 함수
}
C는 A와 B를 public으로 상속받았기 때문에, A와 B의 public 멤버에 자유롭게 접근할 수 있음.obj를 통해 A, B, C의 멤버 함수들을 모두 호출할 수 있음.#include <iostream>
using namespace std;
class A {
public:
void showA() {
cout << "Class A" << endl;
}
};
class B {
public:
void showB() {
cout << "Class B" << endl;
}
};
// C가 A와 B를 동시에 상속받음**
class C : public A, public B {
public:
void showC() {
cout << "Class C" << endl;
}
};
int main() {
C obj;
obj.showA(); // A의 함수 호출
obj.showB(); // B의 함수 호출
obj.showC(); // C의 함수 호출
return 0;
}
D 클래스는 B와 C를 상속받는데, B와 C가 각각 A를 상속받았기 때문에 D 안에는 A 객체가 두 개 존재하게 됨.obj.show(); 호출 시, 어떤 A의 show()를 호출해야 할지 컴파일러가 결정할 수 없음 (모호성 문제 발생).#include <iostream>
using namespace std;
class A {
public:
void show() {
cout << "Class A" << endl;
}
};
class B : public A {}; // A를 상속
class C : public A {}; // A를 상속
// D가 B와 C를 다중 상속
class D : public B, public C {};
int main() {
D obj;
obj.show(); // 컴파일 오류 발생! A가 두 번 상속됨**
return 0;
}
📌 해결 방법: virtual 키워드를 사용하여 공통 조상(A)이 한 번만 상속되도록 만들어야 함.
virtual 키워드는 B와 C가 A를 상속할 때 선언해야 함.D에서 따로 virtual을 선언하지 않아도 자동으로 A가 한 번만 상속됨.#include <iostream>
using namespace std;
class A {
public:
void show() {
cout << "Class A" << endl;
}
};
**// 가상 상속을 적용**
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};
int main() {
D obj;
obj.show(); // 문제 없이 실행됨!
return 0;
}
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A 생성자 호출" << endl; }
};
class B : virtual public A {
public:
B() { cout << "B 생성자 호출" << endl; }
};
class C : virtual public A {
public:
C() { cout << "C 생성자 호출" << endl; }
};
class D : public B, public C {
public:
D() { cout << "D 생성자 호출" << endl; }
};
int main() {
D obj;
return 0;
}
//출력: A 생성자 호출 B 생성자 호출 C 생성자 호출 D 생성자 호출