부모에선 protected
자식에선 public 으로 상속 받는 경우가 많음
(부모에서 private이면 자식에서 상속해주지 못하기 때문에)
- 가상함수(virtual function)의 필요성
- 상속 받은 함수(부모)를 실행하지 않고 자신(자식)의 함수를 실행
- 부모도 있고 자식도 있을 때 자식을 우선하는 것이 overriding
overriding : 가상함수 구현
- 부모 클래스의 멤버함수와 같은 이름의 함수를 자식 클래스에서 재정의하여 사용
- 자식 클래스에서 재정의되는 가상함수는 부모 클래스와 함수의 리턴값, 매개변수 개수, 형이 완전히 같아야 함
overloading : 같은 이름의 함수가 매개변수에 따라 다르게 정의됨. 컴파일 타임에 결정.
overriding : 기본 클래스의 가상 함수를 파생 클래스에서 재정의함. 런타임에 결정. 자식이 똑같은 이름의 함수를 만들면 부모의 것을 virtual
- 바인딩(binding)
: 변수와 함수에 대한 메모리 할당이나 함수 호출이 발생했을 때 실제로 처리해야하는 명령어들이 결정되는 시점
- 정적(static) 바인딩, early : 컴파일시 결정 - overloading
- 동적(dynamic) 바인딩, late : 실제 실행(run time)할 때 결정 - overriding
#include <iostream>
using std::cout;
void sub();
int main()
{
cout << "start\n";
sub();
sub();
sub();
return 0;
}
void sub()
{
int x = 10;
//동적 바인딩, run-time시
static int y = 10;
//정적 바인딩, y의 초기값은 컴파일시 10으로
//정해지며 실행시에 이 선언문은 실행하지 않음
cout << x << y << '\n';
x++;
y++;
}
- static이 없는 경우(동적 바인딩) : 지역변수는 블럭 내에서만 유효하기 때문에 나오면 사라짐
- x는 쓰레기값인데 y는 10이 생김 왜? : static을 붙이니까 컴파일시 실행. 이미 나타난거임
static이 붙어있으면 런타임 중에 실행되는게 아니라서 뛰어넘고 다음 줄로 넘어감
컴파일 시 실행 = 실행파일에 자리를 잡고있는거임. 프로그램이 끝나야지 사라짐
일반 변수들은 해당 블럭을 지나갈때 나타나고 블럭을 나가면 바로 사라짐
그래서 위 코드 실행하면 x는 10 11 -> 10 11 이렇게 반복인데 y는 10 11 12 13 1씩 증가하게 됨
- auto
- 정적(static) 멤버변수
특징
- 언제 사용하는가? : 객체들이 정보를 공유할 목적으로 사용하는 변수
- 모든 객체가 공유
#include <iostream>
using std::cout;
class Point {
int x;
int y;
static int count; //선언
public:
Point() { cout << ++count; }
~Point() { cout << --count; }
};
int Point::count = 0; //정의
int main()
{
Point p1, p2, p3;
return 0;
}
count는 static이라 안보이는 것
count 는 한번만 만들어지고 ++되서 123210 출력
- 에러가 발생하는 이유 : static 멤버변수를 선언할 때, 클래스 외부에서 꼭 한번 정의해줘야 함.(초기값은 안줘도 기본 0)
- 클래스 선언이 기억 장소를 할당하는 것이 아니므로 정적 멤버변수는 클래스 밖에서 초기화를 함(정의함, 초기화 값이 없으면 0으로 초기화 됨)
- 가상함수(virtual function)
가상함수 형식
class 클래스명 {
virtual 리턴형 함수명(매개변수) { }
);
class A //부모
{
public:
virtual int SS(int i) { return(i * 2); }
//자식아! 이 함수가 마음에 들지 않으면 재정의해라. 그럼 이 함수는 무시될 거야.
//그런데 함수명, 리턴형, 매개변수의 개수와 자료형은 같아야 하고 기능만 다르게 만들어야 한다.
};
class B : public A //자식
{
public:
int SS(int i) { return(i * 3); }
//부모클래스 A의 SS함수가 마음에 들지 않아 자식클래스에서 재정의
};
* 다른 언어에서는 override 사용함
- C언어의 cast연산자
- (자료형) 값_이나_변수
- (int)x, (char)ch, (double)sum
#include <stdio.h>
int main(void)
{
int x = 10, y = 4;
double z;
printf("%d\n", 10 / 4);//2
printf("%f %f %f\n", 10 / 4.0, 10.0 / 4, 10.0 / 4.0);//모두 2.500000
printf("%d\n", x / y);// 2
z = x / y;//double형인 z에 2를 저장하면 소수점만 더 붙음
printf("%f\n", z);// 2.000000
z = (double)x / y;//10.0/4
printf("%f\n", z);// 2.500000
z = x / (double)y;//10/4.0
printf("%f\n", z);// 2.500000
z = (double)x / (double)y;//10.0/4.0
printf("%f %lf\n", z, z);// 2.500000 2.500000
return 0;
}
+ 새로 추가된 cast연산자
- static_cast : 컴파일시 타입 변환 수행
- dynamic_cast : 런타임에 타입 변환 수행
- const_cast
- reinterpret_cast
- static_castd 예제
#include <iostream>
using namespace std;
int main()
{
int x = 10, y = 4;
cout << x / y << endl; //2
cout << (double)x / y << endl; //2.5
cout << static_cast<double>(x) / y << endl; //2.5
return 0;
}
- 순수가상함수(pure virtual function)
virtual double area()=0;
- 앞에 'virtual', 뒤에 '=0'
- - 부모 클래스에서 자식 클래스에서 반드시 구현해야하는 메서드를 정의
- 자식 클래스가 어떤 메서드를 구현해야하는지 강제하고 명시
#include <iostream>
using std::cout;
using std::endl;
class Shape {//추상클래스(abstract class)
protected:
double x, y;
public:
//virtual double area() { return 0; } //주석처리
// 일반 가상 함수
virtual double area()=0; //주석 해제
}; // 순수 가상 함수
class Rectangle : public Shape {
private:
double height, width;
public:
Rectangle(double h, double w)
{
height = h; width = w;
}
double area() { return(width * height); }
};
class Triangle : public Shape {
private:
double height, width;
public:
Triangle(double h, double w)
{
height = h; width = w;
}
double area() { return(width * height / 2.0); }
};
int main()
{
Shape ss; // virtual double area()=0;
// 윗줄 주석과 같이 순수 가상함수가 있으면 추상클래스이고
// 추상클래스는 객체(인스턴스)를 만들 수 없음
Shape* p; //포인터 객체는 가능
Rectangle nemo(10.0, 20.0);
Triangle semo(10.0, 20.0);
p = &nemo; //자식의 주소를 부모 포인터에 대입
cout << "네모면적:" << p->area() << endl; //Rectangle::area()
p = &semo;
cout << "세모면적:" << p->area() << endl; //Triangle::area()
return 0;
}
//네모면적:200
//세모면적:100
*에러발생
- 클래스에 순수가상함수가 하나라도 있으면 그 클래스를 추상클래스 라고함
#include <iostream>
using std::cout;
using std::endl;
class Shape {//추상클래스(abstract class)
protected:
double x, y;
public:
//virtual double area() { return 0; } //주석처리
// 일반 가상 함수
virtual double area()=0; //주석 해제
}; // 순수 가상 함수
//기능 없는 함수를 호출하고있는거라 에러발생.
class Rectangle : public Shape {
private:
double height, width;
public:
Rectangle(double h, double w)
{
height = h; width = w;
}
double area() { return(width * height); }
};
class Triangle : public Shape {
private:
double height, width;
public:
Triangle(double h, double w)
{
height = h; width = w;
}
double area() { return(width * height / 2.0); }
};
int main()
{
//Shape ss; // virtual double area()=0; 추상클래스는 객체를 만들 수 없음.
// 윗줄 주석과 같이 순수 가상함수가 있으면 추상클래스이고
// 추상클래스는 객체(인스턴스)를 만들 수 없음
Shape* p; //포인터 객체는 가능
Rectangle nemo(10.0, 20.0);
Triangle semo(10.0, 20.0);
p = &nemo; //자식의 주소를 부모 포인터에 대입
cout << "네모면적:" << p->area() << endl; //Rectangle::area()
p = &semo;
cout << "세모면적:" << p->area() << endl; //Triangle::area()
return 0;
}
//네모면적:200
//세모면적:100
추상클래스는 객체를 만들 수 없음.
#include <iostream>
using std::cout;
class Dot // 부모
{
public:
void draw() { cout << "Dot\n"; }
void print() {
cout << "Dot 클래스\n";
draw();
}
};
class Line :public Dot // 자식
{
public:
void draw() { cout << "Line\n"; } //
};
int main()
{
Line line;
line.print(); // Dot 클래스
// Dot
return 0;
}
#include <iostream>
using std::cout;
class Dot // 부모
{
public:
virtual void draw() { cout << "Dot\n"; } // 자식이 바꿔 사용할 수 있도록
void print() {
cout << "Dot 클래스\n";
draw();
}
};
class Line :public Dot // 자식
{
public:
void draw() { cout << "Line\n"; } //
};
int main()
{
Line line;
line.print(); // Dot 클래스
// Line
return 0;
}
+ override
#include <iostream>
using std::cout;
class Dot // 부모
{
public:
virtual void draw() { cout << "Dot\n"; } // 자식이 바꿔 사용할 수 있도록
void print() {
cout << "Dot 클래스\n";
draw();
}
};
class Line :public Dot // 자식
{
public:
void draw() override { cout << "Line\n"; } // c++ 11에 도입된 문법. override
};
int main()
{
Line line;
line.print(); // Dot 클래스
// Line
return 0;
}
'C++' 카테고리의 다른 글
12. 상속 (inheritance) (2) | 2024.11.19 |
---|---|
11. 함수 중첩, 디폴트 인자 (0) | 2024.11.12 |
8. const 동적 메모리 할당 (new, delete) (8) | 2024.11.05 |
7. 객체와 멤버, 생성자/소멸자, this 포인터 (0) | 2024.10.29 |
6. 접근 속성 클래스와 객체 만들기 (2) | 2024.10.15 |