2012-12-07 4 views
0

편집 : 코드 중 아무 것도 내 것이 아니며 모든 것이 나에게 주어졌으며 객체 할당 방법 관점에서 분석했습니다.C++ 메모리 할당 - 서브 클래스를 클래스에 할당

메모리 할당에 어려움을 겪고 있습니다. 지난 5 시간 동안 여기서 수백 건의 예를 보았습니다. 아마이 말은 잘 못된 것 같아서 미리 사과드립니다.

1.) 버전 2가 클래스 B 대신 클래스 A의 f()를 인쇄하는 이유를 이해할 수 없습니다. 라인

A* objA1 = objB; 

는 A 유형의 객체를 가리키고 그것이 objB는, B (2,3)를 가리키는 곳에 그 주소를 할당되어 있는지, 포인터 objA1 선언된다. 나는 "heap-dynamic objects라면 b1을 a1에 할당 할 수있다"라는 문장을 읽었다. objA1-> f()를 호출하면 간단히이 위치로 이동한다고 말합니까? 아, B를 찾았습니까? 잘 A로 캐스팅하고 f()를 호출하십시오.

2.) 버전 1을 objB 슬라이스로 생각했을 것입니다. A가 할당 된이 객체를 설정했기 때문에 B가 더 큽니다. 그러나 만약 내가 약을 넣으면 < < objB.bf; 이 과제 후에도 여전히 유효합니다. A objA1 = objB; 정적으로 objA1을 선언하지 않습니까? 그리고 다시 한번, 왜 B의 f()를 인쇄하지 않을까요?

3.) 두 objA1 할당의 차이점은 무엇입니까? 어떤 기능이 2 가지 중 하나에서만 작동합니다. 낡은 종류의 분류를 원한다면 "heap-dynamic"이라고 부를 수 있을까요?

class A { 
    private: 
    int a; 
    public: 
    A(int ia) {a = ia;} 
    void f() { 
     cout << "Call to method f defined in class A" << endl; 
    } 
}; 
class B : public A { 
    private: 
    int b; 
    public: 
    B(int ia, int ib) : A(ia) {b = ib;} 
    void f() { 
     cout << "Call to method f specialized in class B" << endl; 
    } 
    void bf() { 
     cout << "Call to class B own method bf" << endl; 
    } 
}; 
// C++ driver - Version 1 
void main() { 
    A objA = A(1); 
    B objB = B(2,3); 

    objA.f(); 
    objB.f(); 
    objB.bf(); 

    A objA1 = objB; 
    objA1.f(); 
} 

// C++ driver - Version 2 
void main() { 
    A* objA = new A(1); 
    B* objB = new B(2,3); 

    objA->f(); 
    objB->f(); 
    objB->bf(); 
    A* objA1 = objB; 
    objA1->f(); 
} 
+0

'main'은'void'가 아닌'int'를 반환합니다. – GManNickG

답변

1

C++은 기본적으로 동적 디스패치를 ​​사용하지 않습니다. 즉, pX *p으로 선언 될 때 p->f()을 호출하면 p이 가리키는 인스턴스의 동적 유형에 관계없이 항상으로 전화를 걸므로 X::f()이됩니다.동적 디스패치를 ​​사용하려면 함수를 virtual으로 선언해야합니다. 이것은 모든 멤버 함수가 암시 적으로 virtual 인 Java/C#과는 대조적입니다.

실제로 "버전 1"의 슬라이스가 발생하지만 objB은 어딘가에 할당 되어도 영향을받지 않습니다. 슬라이싱의 영향을받는 것은 objA이며 A의 일부가 아닌 objB 부분을 무시합니다.

+0

두 개의 objA1 과제 간의 차이점을 알려주십시오. 어떤 기능이 2 가지 중 하나에서만 작동합니다. 낡은 종류의 분류를 원한다면 "heap-dynamic"이라고 부를 수 있을까요? –

+0

@ caleb.breckon'A objA1 = objB; (여기서'objB'는'B' 타입 임)는 스택에'A' 타입의 객체'objA1'을 만듭니다 (변수의 값은 객체 자체입니다). 'A * objA1 = objB;'(여기서'objB'는'B *'타입입니다)는 ** 포인터 **를 복사합니다 - 할당 후에'objA1'과'objB' (둘 다 포인터입니다)는 같은 것을 가리 킵니다 'new'를 사용하여 힙에 할당 된'objB' 인스턴스입니다. – Angew

2

당신은 당신이 기본 클래스에서 virtual로 (베이스 포인터를 통해) 다형 호출하고자하는 귀하의 함수를 선언해야합니다. 컴파일러에서 개체에 대한 포인터 (또는 참조)를 통해 virtual 함수를 호출하면 정적 형식이 아닌 동적 형식 인에 대해 함수를 찾습니다. 그래서 단순히 A에 함수 정의 앞에 virtual 스틱 :

virtual void f() { 
    cout << "Call to method f defined in class A" << endl; 
} 

귀하의 라인 A objA1 = objB; 실제로에만 objA1에의 A 부분을 통해 복사하여 B 객체를 슬라이스 않습니다. A의 회원 기능은 objA1으로 만 호출 할 수 있습니다. 그러나 objB은 여전히 ​​동일한 객체이며 항상 B이며 모두 B의 멤버 함수를 사용할 수 있습니다. 기꺼이 objB->bf()에 전화 할 수 있지만 objA->bf()이나 objA1->bf()은 안됩니다.

확실하지 않은 경우 함수를 호출하는 객체의 유형을 살펴보십시오. A 인 경우 A의 기능에만 전화를 걸 수 있으며, 마찬가지로 B으로 전화 할 수 있습니다. 포인터를 통해 액세스하고 virtual 함수를 호출하는 경우 포인터가이라고 말하는 유형이 아니라 객체의 dynamic type에 속한 함수가 호출됩니다.

+0

두 objA1 과제의 차이점을 알려주십시오. 어떤 기능이 2 가지 중 하나에서만 작동합니다. 낡은 종류의 분류를 원한다면 "heap-dynamic"이라고 부를 수 있을까요? –

+0

@ caleb.breckon 첫 번째는 단지'B *'포인터를'A *'에 할당하는 것입니다 - 완전히 괜찮 았고 객체가 가리키는 객체를 복사하지 않기 때문에 객체 슬라이스가 발생하지 않습니다. 그러나'A' 타입의 객체에'B' 타입의 객체를 할당하면 실제로 한 객체의 값을 다른 객체에 복사하고 분명히'B'의 값은 'A' 그래서 당신은 객체 조각을 얻을 수 있습니다. –