有多重继承
class A{};
class B{};
class C: public A, public B{};
当我做什么时会发生什么
C *c = new C;
A *a = c;
B *b = c;
A *a1 = new C;
B *b1 = new C;
第一个C实例会怎样?是否将C指定给A类型的指针切片对象,那么A只指向包含A成员的C的一部分? 如果是这样,它怎么知道什么时候到顶?如果C包含A部分和B部分,而A部分从偏移0开始,它如何知道要停止哪个偏移?
感谢您的帮助。
答案 0 :(得分:3)
A
,作为两者的孩子,是 B
而是 c -> +++++++++++++++++++++
+ C +
a -> + +++++++++++++++++ +
+ + A + +
+ +++++++++++++++++ +
+ +
b -> + +++++++++++++++++ +
+ + B + +
+ +++++++++++++++++ +
+ +
+ C's own members +
+ +
+++++++++++++++++++++
。所以,当你向上转换指针时,没有切片发生(为什么还会发生?)但是指针指向对象的适当部分。标准图表是smth。像
a
b
和virtual
都指向相应的子对象。
它是如何知道的? - 好吧,编译器会创建内存布局,它肯定知道应该指定哪些虚拟地址指针,以及向上/向下转换如何相当于指针偏移量。
请注意,当您使用普通指针到base作为对象的唯一(并拥有)引用时,您应该声明base的析构函数public class TakingQuiz extends AppCompatActivity {
TextView que;
TextView sco;
TextView qn;
Button opt1;
Button opt2;
Button opt3;
Button opt4;
String RecieversId;
Integer mScore = 0;
Integer mQuestionNumber = 1;
String question;
String option1;
String option2;
String option3;
String option4;
String answer;
FirebaseAuth mAuth;
FirebaseUser currentUser;
DatabaseReference mDatabaseReference;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.taking_quiz);
que = (TextView) findViewById(R.id.txtQuestion);
opt1 = (Button) findViewById(R.id.button1);
opt2 = (Button) findViewById(R.id.button2);
opt3 = (Button) findViewById(R.id.button3);
opt4 = (Button) findViewById(R.id.button4);
qn = (TextView) findViewById(R.id.number);
sco = (TextView) findViewById(R.id.score);
qn.setText("1");
sco.setText("Score : 0");
RecieversId = getIntent().getStringExtra("Recievers_Id");
mAuth = FirebaseAuth.getInstance();
currentUser = mAuth.getCurrentUser();
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
updateQuestion();
}
private void updateQuestion() {
mDatabaseReference.child("Users").child(RecieversId).child("Quiz").child("Question1").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
question = dataSnapshot.child("Question").getValue().toString();
answer = dataSnapshot.child("Answer").getValue().toString();
option1 = dataSnapshot.child("Option1").getValue().toString();
option2 = dataSnapshot.child("Option2").getValue().toString();
option3 = dataSnapshot.child("Option3").getValue().toString();
option4 = dataSnapshot.child("Option4").getValue().toString();
que.setText(question);
opt1.setText(option1);
opt2.setText(option2);
opt3.setText(option3);
opt4.setText(option4);
opt1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mQuestionNumber++;
qn.setText("Quesion : " + mQuestionNumber);
if (option1.equals(answer)) {
opt1.setBackgroundColor(Color.GREEN);
mScore++;
sco.setText("Score : " + mScore);
} else
opt1.setBackgroundColor(Color.RED);
sco.setText("Score : " + mScore);
}
});
opt2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mQuestionNumber++;
qn.setText("Quesion : " + mQuestionNumber);
if (option2.equals(answer)) {
opt2.setBackgroundColor(Color.GREEN);
mScore++;
sco.setText("Score : " + mScore);
} else
opt2.setBackgroundColor(Color.RED);
sco.setText("Score : " + mScore);
}
});
opt3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mQuestionNumber++;
qn.setText("Quesion : " + mQuestionNumber);
if (option3.equals(answer)) {
opt3.setBackgroundColor(Color.GREEN);
mScore++;
sco.setText("Score : " + mScore);
} else
opt3.setBackgroundColor(Color.RED);
sco.setText("Score : " + mScore);
}
});
opt4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mQuestionNumber++;
qn.setText("Quesion : " + mQuestionNumber);
if (option4.equals(answer)) {
opt4.setBackgroundColor(Color.GREEN);
mScore++;
sco.setText("Score : " + mScore);
} else
opt4.setBackgroundColor(Color.RED);
sco.setText("Score : " + mScore);
}
});
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
,否则您将无法正确销毁该对象。
答案 1 :(得分:0)
第一个C ++要求所有指令都以分号(;
)结束。
现在提出您的问题:
C的第一个实例会发生什么?
无。 A * a = c;
实际初始化指向动态分配的A *
C对象的*c
指针。它是一个有效的指针转换,因为C是A的子类。事实上,这只是多态的基础。
将C分配给A类型的指针切片对象,所以A只指向包含A成员的C的一部分吗?
转换指针时不会发生切片。 A a1 = *(static_cast<A *>(c));
确实会生成仅包含A部分的切片副本。
如果是这样,它怎么知道何时登顶?
实施细节如何?编译器可以这样做,因为它是在标准中指定的。常见实现在对象地址中使用偏移量。
如果C包含A部分和B部分,A部分从偏移0开始,它如何知道要停止的偏移量?
这又是一个实现细节。但是对于常见的实现,A部分以起始偏移+ sizeof(A)结束。
答案 2 :(得分:0)
将C分配给A类型的指针切片对象
没有。初始化(或分配,但赋值不是你的代码所做的)指针对指向的对象没有影响。
所以A只指向包含A?
成员的C部分
这并不是从切片开始的,因为那并没有发生,但是,a
(这是指针变量的名称,而不是A
)确实指向A
对象中的C
子对象。 A
对象仅包含自己的成员。
它如何知道要停止的偏移?
编译器知道对象需要多大,并且它决定所有已定义类型的确切大小。由于是编制者做出决定,当然它知道它的决定。