-
상속시 부모 private 변수,복사생성자, 깊/얕 복사, 전역변수, 포인터 레퍼런스?, 함수호출규약?쥬신게임아카데미/C++ 2016. 1. 7. 13:19
//------------------------시작----------------------------//
////복사생성자 호출모양
////1. CObj obj(10);
////CObj obj2(obj); //기본적인 ****복사생성자**** 발생
//
////2. 함수 호출시 ****매개변수에 객체를 값에 의해 전달****될때
//void Render(CObj obj) //여기서 CObj obj는 값에의해 전달되는 매개변수이니.. ****복사생성자**** 발생..////3. 함수 내에서 ****객체를 값에 의해 리턴****할떄
//CObj Func()
//{
// CObj obj(10);
// return obj; //obj가 반환값이 CObj값이기 때문에 ****복사생성자**** 발생
//}//CObj(const CObj& rObj)
//{
// cout << "복사생성자" << endl;
// m_iValue = rObj.m_iValue; //일반변수인 이건 원본이든 복사되는것이든 주소는 다르다
////멤버변수로 동적할당 받는게 있다면..반드시 복사시에 문제가 발생한다.
// //***얕은복사
// m_pValue = rObj.m_pValue; //포인터변수인 이건 원본이든 복사되는것이든 같은 주소를 같는다..(새로 동적할당 받지 않는 이상)// //***깊은복사(포인터를 멤버변수로 가지고 있다면 반드시..)
// m_pValue = new int;
// *m_pValue = *rObj.m_pValue;//아래는 깊은복사 문자열 예)
// m_pName = rObj.m_pName;
// strcpy_s(m_pName, strlen(rObj.m_pName) + 1, rObj.m_pName);
//}//------------------------끝----------------------------//
//------------------------시작----------------------------//
// 포인터 레퍼런스 ... int*& iNum
쉽게 이야기하면 이중포인터를 대신하는것인데매개변수나 내부에서 이중포인터 **를 안쓰기 때문에 그냥 매개변수 처럼 쓸 수 있어서 편하다.
void Input(int** ptr)
{
내부에서는 *ptr = new int; 인데
}
void Input(int*& ptr)
이라면..
{
내부에서는 ptr = new int; 로 그냥 사용이 가능한것 처럼 보임..
}
레퍼런스이기 때문에 선언과 동시초기화를 해야하며, 중간에 바꿀 수 없다.
가리키는 대상을 변경할 수 없음, 값을 변경
string name("Hyeven");
string sname("wonjayk");
string &rData = name;
rData = sname;
- name의 값을 sname의 값으로 변경하는 결과 //혹여나 헷갈리면 안됨..!!
추가 포인터 레퍼런스의 경우 조심해야할것..!!
void Test(int*& _iNum)
{
//-----------1번----------------//
int* ptr2 = new int;//포인터 레퍼런스가 ptr1을 가리키고 있는데 ptr1의 주소가
//지금부터는 ptr2의 주소를 가지고 있음..
//즉..이름은 같지만 내용 주소를 ptr1이 ptr2주소를 가지고 있음.. ptr1주소가 붕떠버림..(ptr1주소를 가리키는게 없음..ㅠㅠ)
//ptr1, ptr2가 같은곳(ptr2의 주소)을 바라봄..
_iNum = ptr2; //여기가 중요!//ptr1에(ptr2주소를 가지고 있는..) 값을 100으로 변경
*_iNum = 100;//-----------1번----------------//
//-----------위에포함해서 아래부터 2번--------------//
delete ptr2;
ptr2 = NULL;
//-----------위에포함해서 아래부터 2번--------------//
}void Test1(int& _iNum)
{
int Num = 100;
_iNum = Num;
}void main()
{
int* ptr1 = new int;
*ptr1 = 10;cout << *ptr1 << endl;
cout << ptr1 << endl; //ptr1의 주소Test(ptr1);
//1번때에는 값이 100으로 나옴
//2번때에는 delete ptr2을 해버리기 때문에...test함수를 거친 ptr1이(ptr2주소를 가지고 있는..) 주소가 없어짐..NULL
cout << *ptr1 << endl;
cout << ptr1 << endl; //ptr2의 주소
}//포인터가 보통...
1. 이중포인터 안쓰고
2. *안붙이고 쓸때 편한데....
//------------------------끝----------------------------////----------------------시작-------------------------//
//*********에잇..
//전역변수
//보편적인 사용법은 공용헤더에서 사용할 변수를 먼저 지정해준다.//extern 사용법 다시..!
//전역변수 키워드
extern int g_iValue = 0; //???extern 키워드 선언은 변수의 실제 구현이 외부 파일에 있다는 것을 링커에게 알려준다.
그러니까..
FILE : a.cpp
- int var = 5;
- void main()
- {
- ....
- }
FILE : b.cpp
- #include "a.h"
- int var;
- void func1()
- {
- cout << var << endl;
- ...
- }
의도는 var라는 전역 변수가 모든 파일들에서 사용되기를 원했지만 동일한 이름의 전역 변수의 선언이 a,b 파일 두군데에서 이뤄졌으므로 문법 오류이다.
FILE b.cpp는 아래와 같이 수정되야 한다.
- #include "a.h"
- // 해당 변수의 정의는 외부 파일에 있다.
- extern int var; //이건 정의가 아니라 선언이다. extern 붙으면 선언으로 된다
- // 실제 정의가 아니므로 extern int var = 5; 와같이 초기화가 불가능하다.
- void func1()
- {
- cout << var << endl;
- ...
- }
추가적으로 만약 b파일에서 동일한 이름의 전역 변수를 자신만의 파일내부에서 사용하길 원한다고 할때
var 변수를 static int var 와같이 static 키워드를 사용하여 선언하면 된다.
규칙상 internal 이 external을 가리게 되어 func1 내부에서 사용되는 var는 내부에 선언된 static int var가 되게 된다.
c++에서 linking과정은 internal linking과 external linking이 존재한다.
external linking의 경우 해당 객체의 실체가 외부에 존재하는 것을 허용하는 것이다
그리고 가장 중요한거!! extern 으로 외부에 있다는것을 알리는데
extern으로 정의가 되어있는 변수의 헤더를 include할 필요가 없다. 쓰려고하는 장소에는 다 extern 으로 선언은 해줘야함..!!
알아서 extern하면 알아서 찾는다..
extern 변수와 모듈(함수)의 독립성
프로그램을 개발하면서 extern이 필요한 경우도 있겠지만,
이는 모듈의 독립성을 떨어뜨릴 수 있으므로 사용을 자제하시는 것이 좋습니다.
//----------------------시작-------------------------//
//함수호출규약???
//에러뜰때 함수정의부없으면 void __cdecl 어쩌고..이번시간에는 함수호출규약에 대해 설명드리겠습니다.
함수호출규약이란 함수를 호출 한 후 돌아올 때 까지 스택프레임의 변화를 나타내는 규칙입니다.
함수호출규약에는 대표적으로 3가지 cdecl, stdcall , fastcall 이 있습니다.
우선 cdecl 에 대해 설명드리겠습니다.
1. 인자전달순서가 뒤에서 앞으로 간다.
함수를 호출할때 스택에는 전달하는 인자가 뒤에서 부터 스택에 공간이 생성됩니다.
2. 인자전달방법이 stack을 통한다.
함수에 인자를 전달할때는 stack에 저장되어 전달된다.
3. 인자정리방법은 caller 방식을 따른다.
caller는 함수가 호출되고 기능을 한 후 되돌아가서 인자공간이 정리되는 방식입니다.
4. 주로 c 또는 c++ 에서 기본으로 사용하는 함수호출규약.
그다음으로는 stdcall에 대해서 알아보겠습니다.
1.인자전달 순서가 뒤에서 앞으로 간다.
2. 인자전달방법으로 stack을 통한다.
3. 인자정리방법이 callee방식을 따른다.
이부분이 cdecl과 다릅니다. callee는 호출된 함수내에서 인자를 해제한 후 돌아가는 방식입니다.
이 방식은 인자공간이 해제되는 공간이 정해져 있어서 가변인자함수를 사용하기 어렵다.
4. 윈도우 API (WinAPI)에서 사용되는 함수호출규약
마지막으로 fastcall 함수규약이 있습니다.
1. 인자전달 순서가 뒤에서 앞으로간다.
2. 인자전달방법으로 stack 과 register를 사용한다.
레지스터는 메모리보다 동작 방식이 빠르기 때문에 다른 함수호출규약에 비해 실행속도가 빠르다.
그러나 c언어에서는 그대로 사용하면 형태만 따르기 때문에 코드가 늘어나서 오히려 느려질 수도 있다.
그렇기 때문에 c언어에서는 특별한 방식을 사용해야한다.
레지스터는 ECX와 EDX를 사용하는데 첫번째 인자를 ECX에 두번째 인자를 EDX에 세번째인자부터는 stack에 저장한다.
3. 인자정리방법으로 callee 방식을 따른다.
5. 주로 델파이언어라는 곳에서 기본적인 함수호출규약으로 사용한다.
//----------------------끝-------------------------////***********************상속관련..티이입
//부모클래스의 변수를 public으로 상속받고 그 변수가 부모에서 접근자가 public일 경우
//자식클래스의 함수안에서 사용은 가능하나..생성자에서 이니셜 라이징이 안된다..왜냐면 자식클래스의 변수가 아니기 때문이다..
//
//만약에 부모클래스의 변수 접근자가 private일 경우에는 자식에서 접근이 안됨..함수든 어디든..
//
//----------------------끝-------------------------//'쥬신게임아카데미 > C++' 카테고리의 다른 글
쓰레드 관련 (0) 2016.03.29 static 변수 특징 (0) 2016.01.06 함수 반환값 const / 멤버함수 const (0) 2016.01.06