https://www.geeksforgeeks.org/c-plus-plus-gq/class-and-object-gq/
C++에서 구조체는 클래스와 동일한 방식으로 작동한다.
하지만 사용하는 철학에 따라 차이를 보인다. 바로 '구현 세부 정보'를 공개하느냐 숨기느냐 차이이다.
구조체는 기본적으로 사용자에게 구현 세부 정보를 숨기지 않는 반면, 클래스는 기본적으로 숨겨서 액세스를 방지한다.
source: https://www.geeksforgeeks.org/structure-vs-class-in-cpp/
클래스는 기본적으로 데이터를 숨기고(캡슐화), 데이터를 처리하는 로직을 감추어 특정 기능을 public 함수로 제공하는 반면, 구조체는 데이터들의 집합을 다루기 위해 사용한다.
C언어에 구조체가 도입되었을 땐 객체의 개념이 없었다. 따라서 빈 구조체의 크기를 0으로 유지할 수 있었다.
그러나 C++에서 구조체/클래스의 크기는 함수 호출을 위해 적어도 1바이트(최소 바이트) 이상을 가져야하며, 빈 구조체/클래스의 크기는 1바이트이다.
struct EmptyStruct {
};
class EmptyClass {
};
{
cout << sizeof(EmptyStruct) << endl; // => 0
cout << sizeof(EmptyClass) << endl; // => 0
}
빈 클래스(empty class): 빈 클래스란 데이터 멤버를 갖지않는 클래스를 의미한다. 멤버 함수의 유무는 따지지 않는다.
단순히 객체가 없는 클래스에는 할당된 공간이 필요하지 않는다. 공간은 클래스가 객체화 될 때 할당되므로 컴파일러는 고유 주소 식별을 위해 빈 클래스 객체에 적어도 1바이트 이상을 할당한다.
적어도 1바이트만큼이라도 공간을 할당받아야지만 주소를 가질 수 있게 되고, 주소를 가진 각 객체는 서로 구별될 수 있다.
// Creating an Empty class
class Empty {
};
// Driver Code
int main()
{
Empty a, b;
if (&a == &b)
cout << "Impossible " << endl;
else
cout << "Fine " << endl;
// "Fine" 출력~!
return 0;
}
한 가지 주의할 점은 빈 클래스를 상속받았다고, 빈 클래스의 크기 1바이트가 추가되는 것은 아니다.
#include <iostream>
using namespace std;
// Creating an Empty Class
class Empty {
};
// Creating a Derived Class
class Derived : Empty {
int a;
};
// Driver Code
int main()
{
cout << sizeof(Derived); // => 4
return 0;
}
같은 클래스형 객체들은 비정적 데이터 멤버를 공유하지 않는다. 각 객체의 주소에 존재하는 고유한 공간을 가진다. 반면 정적 데이터 멤버는 공유하고, 각 객체의 공간에 포함되지 않는다(Data 영역에 존재).
비정적 멤버 함수의 경우 객체들이 공유한다.
32비트 시스템에서 포인터의 크기는 4바이트,
64비트 시스템에서 포인터의 크기는 8바이트이다.
32비트 시스템이라고 가정하였을 때, sizeof(Test*)
는 4이고(Test 클래스 포인터 크기는 4바이트), sizeof(t)
는 객체의 크기를 의미하므로 8(바이트)이다.
static 멤버는 각 객체의 공간에 포함되지 않기에 12(바이트)는 오답이다.
기본 자료형 변수와 마찬가지로 이름이 같고 범위가 다른 2개의 객체를 생성할 수 있다.
같은 범위, 가까운 범위에 선언된 변수가 우선되기에,
t.get();
cout << .. << t.i << ..;
에서는 지역변수가 참조되고,
::t.get();
cout << .. << ::t.i << ..;
과 같이 ::
전역 변수 연산자를 통해 전역변수를 참조할 수 있다.
static virtual void func(); // 컴파일 에러
다른 객체를 멤버로 가지는 관계면 연관 관계라 할 수 있다.
멤버 객체와 whole(전체)와 part(부분)의 관계를 가진다.
집합과 마찬가지로 whole(전체)와 part(부분)의 집합 관계를 나타내지만 보다 더 강한 집합을 의미
강한 집합이란 뜻은 part가 whole에 종속적이어서 part가 whole의 소유란 의미.
반대로 약한 집합은 part가 whole에 대해 독립적이어서 whole이 part를 빌려 쓰는 것과 비슷함.
인스턴스가 공유되는 경우
인스턴스가 공유되지 않는 경우
추상 클래스 멤버도 초기화 할 수 있다.
class Base {
private:
string name;
public:
Base(string s) {
name = s;
}
// 순수 가상함수
virtual void pureVirtualFunc() = 0;
void printInfo() {
cout << "name: " << name << endl;
}
};
class Derived : public Base {
private:
int age;
public:
Derived(string name, int age) : Base(name), age(age)
{}
// 순수가상함수 오버라이딩
void pureVirtualFunc() override {
cout << "override func()" << endl;
}
void printInfo() {
Base::printInfo();
cout << "age: " << age << endl;
}
};
int main() {
Derived d("jin", 28);
d.pureVirtualFunc();
d.printInfo();
}