여기서 많은 일들이 진행되고 있습니다. 코드는 유효하지만 질문에 잘못된 가정이 있습니다. 당신은
"B :: 게타 반환 [...] 자체에 값 20을 할당, 그 이후로"
이 (내 강조)이 정확하지 않은 말했다. getA는 이 아니며 개체를 수정합니다. 이를 확인하기 위해 메서드 서명에 const
을 넣으면됩니다. 나는 완전히 설명 할 것이다.
A getA() const {
cout << this << " in getA() now" << endl;
return (((A)*this) = 20);
}
그럼 어떻게 될까요? 내 sample code 보면 (나는이 답변의 끝에 내 성적 증명서를 복사 한) :
A a = 10;
이것은 생성자는 A를 선언합니다. 꽤 똑바로. 이 다음 라인은 :
B b; b.val_ = 15;
B는 생성자가없는, 그래서 (A에서 상속)의 val_ 멤버에 직접 작성해야합니다. 이 superfically이하는 것처럼 보일 수 있지만, 이것은 b
을 수정하지 않습니다
b.getA();
: 우리는 다음 라인, A c = b.getA();
을 고려하기 전에
, 우리는 매우 신중하게 간단한 표현을 고려해야합니다.
결국, 내 샘플 코드는 b.val_
을 출력하고 여전히 15와 같습니다. 20으로 변경되지 않았습니다. c.val_
은 물론 20으로 변경되었습니다.
getA
을보고 (((A)*this) = 20)
이 표시됩니다. 이 문제를 해결해 보겠습니다.
this // a pointer to the the variable 'b' in main(). It's of type B*
*this // a reference to 'b'. Of type B&
(A)*this // this copies into a new object of type A.
여기서 일시 중지 할 수 있습니다. 이 값이 (A&)*this
이거나 심지어 *((A*)this)
이라면 더 간단한 선이됩니다. 그러나 (A)*this
이므로 유형 A의 새 객체를 만들고 관련 슬라이스를 b에서 복사합니다.
(추가 사항 : 슬라이스를 복사하는 방법을 문의하십시오. B&
참조가 있으며 새 A
을 만들고 싶습니다.기본적으로 컴파일러는 복사 생성자 A :: A (const A&)
을 만듭니다. B&
참조가 자연스럽게 const A&
으로 캐스팅 될 수 있기 때문에 컴파일러에서 사용할 수 있습니다.)
특히 this != &((A)*this)
입니다. 이것은 당신에게 놀라운 일일 수 있습니다. (추가 : 다른 한편으로 this == &((A&)*this)
보통 (virtual
방법)이 있는지 여부에 따라에) 이제 우리는이 새로운 객체를 가지고
, 우리는이 새로운 값으로 수를두고
((A)*this) = 20
볼 수 있습니다 . 이 진술은 이 아니며은 this->val_
에 영향을 미칩니다.
getA
이 A&
을 반환하도록 변경하면 오류가 발생합니다. 먼저, operator=
의 반환 값은 const A&
이며 따라서 A&
으로 반환 할 수 없습니다. 그러나 반환 유형으로 const A&
이 있더라도 getA 내에서 생성 된 임시 로컬 변수에 대한 참조가됩니다. 그러한 것을 반환하는 것은 정의되지 않았습니다.
마지막으로, 우리는 게타 값에 의해 복사 를 반환 현재 코드가 잘 안전하고 왜 c
은 게타
A c = b.getA();
에서 값 반환이 복사본을 걸릴 것으로 볼 수있다 -한정된.
== 다음 @Kerrek SB와 @Aaron McDaid의 도움으로 면밀하게 조사한 후 전체 프로그램 ==
#include <iostream>
using namespace std;
struct A {
int val_;
A() { }
A(int val) : val_(val) { }
const A& operator=(int val) {
cout << this << " in operator= now" << endl; // prove the operator= happens on a different object (the copy)
val_ = val;
return *this;
}
int get() { return val_; }
};
struct B : public A {
A getA() const {
cout << this << " in getA() now" << endl; // the address of b
return (((A)*this) = 20);
// The preceding line does four things:
// 1. Take the current object, *this
// 2. Copy a slice of it into a new temporary object of type A
// 3. Assign 20 to this temporary copy
// 4. Return this by value
} // legal? Yes
};
int main() {
A a = 10;
B b; b.val_ = 15;
A c = b.getA();
cout << b.get() << endl; // expect 15
cout << c.get() << endl; // expect 20
B* b2 = &b;
A a2 = *b2;
cout << b2->get() << endl; // expect 15
cout << a2.get() << endl; // expect 15
}
'const A & operator = (int val) {val_ = val; }'return 문이 누락 되었습니까? – ruakh
음,'B :: getB'가 없지만 B :: getA'는 A의 인스턴스가 아닌 B의 인스턴스 (A의 하위 클래스)를 반환합니다. 이것은 매우 모호한 코드이지만 표면적으로, 완벽하게 합법적이다. –
@ruakh : 그렇게 보입니다. :) – netcoder