Hided Data and Codes
Encapsulation을 사용하는 이유
class C {
int n;
public:
S(int); // Constructor Declaration
S() {n=0;} // Constructor Definition
};
S::S(int) {
n=1;
}
int main() {
S s; // calls S::S()
S s2(10); // calls S::S(int)
}
위의 내용은 클래스를 정의하는 방법이다. 다양한 방법으로 클래스의 객체를 만들고 다양한 형태의 생성자로 표현할 수 있다.
S():n(0) {}
#include <iostream>
using namespace std;
class Point {
double x;
double y;
public:
Point();
Point(int x, int y);
void setPoint(int x, int y);
int getX() const;
int getY() const;
Point operator+(const Point& point);
Point& operator=(const Point& point);
};
Point::Point() {
x = y = 0;
}
Point::Point(int x_, int y_) {
x = x_;
y = y_;
}
void Point::setPoint(int x_, int y_) {
this->x = x_;
this->y = y_;
}
int Point::getX() const {
return x;
}
int Point::getY() const {
return y;
}
Point Point::operator+(const Point& point) {
Point hello;
hello.x = this->x + point.x;
hello.y = this->y + point.y;
return hello;
}
Point& Point::operator=(const Point& p) {
this->x = p.x;
this->y = p.y;
return *this;
}
std::ostream& operator<<(std::ostream& os, const Point& point) {
return os << point.getX() << " " << point.getY() << '\n';
}
int main() {
Point* pP1, * pP2;
pP1 = new Point;
pP2 = new Point(1, 2);
pP1->setPoint(10, 20);
*pP2 = *pP2 + *pP1;
cout << "x: " << pP1->getX() << ", y: " << pP1->getY() << '\n';
cout << *pP2 << '\n';
delete pP1;
delete pP2;
}
is-relationship
the Derived Class is a Base Class
** a Derived Class has all data and functions of a Base Class
the Base Class is not a Derived Class
** a Base Class has no whole data and functions of a Derived Class.
#include <iostream>
using namespace std;
class Base {
public:
void f();
};
void Base::f() {
cout << "in function 'Base::f()'\n";
}
class Derived : public Base {
public:
void g();
};
void Derived::g() {
cout << "in function 'Derived::g()'\n";
}
int main() {
Base b;
Derived d;
d.f(); //in function 'Base::f()'
d.g(); //in function 'Derived::g()'
}
#include <iostream>
#include <string>
using namespace std;
class Text {
string text;
public:
Text(const string& t) : text(t) {}
virtual string get() const {
return text;
}
virtual void append(const string& extra) {
text += extra;
}
};
class FancyText : public Text {
string left_bracket;
string right_bracket;
string connector;
public:
FancyText(const string& t, const string& left, const string& right, const string& conn)
: Text(t), left_bracket(left), right_bracket(right), connector(conn) {}
string get() const override{
return left_bracket + Text::get() + right_bracket;
}
void append(const string& extra) override {
Text::append(connector + extra);
}
};
class Fixed : public Text {
public:
Fixed() : Text("Fixed") {}
void append(const string&) override {}
};
int main() {
Text t1("plain");
FancyText t2("fancy", "<<", ">>", "***");
Fixed t3;
cout << t1.get() << endl;
cout << t2.get() << endl;
cout << t3.get() << endl;
cout << endl;
t1.append("A");
t2.append("A");
t3.append("A");
cout << t1.get() << endl;
cout << t2.get() << endl;
cout << t3.get() << endl;
cout << endl;
t1.append("B");
t2.append("B");
t3.append("B");
cout << t1.get() << endl;
cout << t2.get() << endl;
cout << t3.get() << endl;
cout << endl;
}
Access Protection of Base Class

class Base {
};
class Derived : {TYPE} Base {
};
#include <iostream>
using namespace std;
class Base {
public:
void f();
};
void Base::f() {
cout << "in function 'Base::f()'\n";
}
class Derived : private Base {
public:
void g();
};
void Derived::g() {
Base::f();
cout << "in function 'Drived::g()'\n";
}
int main() {
Base b;
Derived d;
b.f();
d.g();
}
private하게 상속받았을 경우, Derived 클래스의 객체는 Base 클래스의 함수를 불러오는 순간 compile Error가 발생한다. 아래와 같은 방식으로 Derived 클래스의 객체가 Derived 클래스 안에 있는 함수를 불러오는 것은 아무런 문제가 발생하지 않는다.
위와 같은 방식은 Derived::g()를 호출했을 때에 Base의 f()도 호출되게 되는데, 이 부분은 private function f() can be invoked privately.
class Derived : private Base {
public:
void g();
};
void Derived::g() {
cout << "in function 'Drived::g()'\n";
}
int main() {
Base b;
Derived d;
b.f();
d.g();
}
C++에서는 다른언어들과는 다르게 여러 개의 Base Class로부터 상속받을 수 있다. 이것을 우리는 Multiple Inheritance라고 부른다.
class Derived : public Base1, public Base2, public Base3 {
};
The virtual specifier indicates that the designer of the Base class intends for derived classes to be able to customize the behavior of the virtual methods.
The exact behavior of these methods (in the Derived class) will be different in some way from their implementation in the Base class.
Binding이란 프로그램 소스에 쓰인 각종 내부 요소, 이름 식별자들에 대해 값 또는 속성을 확정한 과정을 의미.
프로그램을 위한 변수, 함수들은 그 내용을 저장할 메모리를 할당해야 한다. 그 이전에 변수 및 함수의 타입과 값이 결정되어야 하는데, 이 타입과 값을 결정하는 과정을 의미.
Static Binding(정적 바인딩)은 변수 및 함수가 컴파일 시점에 이루어지는 바인딩을 뜻함.
소스 상에 명시적으로 타입과 그 타입의 변수명을 선언하는 것.
Static Binding is relatively easy to understand: the method to execute depends on the declared type of the variable upon which the method is invoked.
Static Binding의 장점
#include <iostream>
using namespace std;
class Base {
public:
void f() {
cout << "in function 'Base::f()'\n";
}
virtual void vf() {
cout << "in function 'Base::vf()'\n";
}
};
class Derived : public Base {
public:
void f() {
cout << "in function 'Derived::f()'\n";
}
void vf() override {
cout << "in function 'Derived::vf()'\n";
}
};
int main() {
Base b;
Derived d;
b.f(); //in function 'Base::f()'
b.vf(); //in function 'Base::vf()'
d.f(); //in function 'Derived::f()'
d.vf(); //in function 'Derived::vf()'
}
Dynamic Binding(동적 바인딩)이란 바인딩 과정이 실행 도중 이루어지는 것.
#include <iostream>
using namespace std;
class Base {
public:
void f() {
cout << "in function 'Base::f()'\n";
}
virtual void vf() {
cout << "in function 'Base::vf()'\n";
}
};
class Derived : public Base {
public:
void f() {
cout << "in function 'Derived::f()'\n";
}
void vf() override {
cout << "in function 'Derived::vf()'\n";
}
};
int main() {
Base* p;
Base b;
Derived d;
p = &b;
p->f(); //in function 'Base::f()'
p->vf(); //in function 'Base::vf()'
p = &d;
p->f(); //in function 'Base::f()'
p->vf(); //in function 'Derived::vf()'
}
In the case of virtual method invoked via a pointer, the running program, not the compiler, determines exactly which code to execute. The process is known as dynamic binding or late binding.
Dynamic Binding의 장점