为什么基类对象的私有成员仍然从派生类中分配?

时间:2016-04-19 11:25:43

标签: c++ inheritance

在以下代码中,CirclePoint的公共继承,其中x的私有成员yPoint无法访问。但是,在将Circle c分配给Point p时,我发现p实际上可以为xy获得正确的值。为什么会这样?

#include<iostream>
using namespace std;
class Point {
public: Point(float x = 0, float y = 0);
        void display();
private:
    float x, y;
};
Point::Point(float a, float b)
{
    x = a; y = b;
}
void Point::display() {
    cout << x <<'\t'<< y << endl;
}
class Circle :public Point
{
public: Circle(float x = 0, float y = 0, float r = 0);
private:
    float radius;
};
Circle::Circle(float a, float b, float r) :Point(a, b), radius(r) {}

int main()
{
    Circle c(10, 10, 15);
    Point p = c;
    p.display();
    return 0;
}

输出:

10    10

6 个答案:

答案 0 :(得分:1)

Circle::Circle(float a, float b, float r) :Point(a, b), radius(r) {}

Circle派生自Point,因此在上面的Circle构造函数行中调用:

Point(a, b)

它正在使用传入的值a和b初始化基类Point,其构造函数将它们分配给x和y。

答案 1 :(得分:0)

您无权访问变量xy,因为它们是私有的。但您可以访问公共方法display()display()是类Point的公共方法,可以访问私有变量。

换句话说,您可以调用方法display(),但无法直接访问私有变量xy

答案 2 :(得分:0)

private bool ParseContainsExpression(MethodCallExpression expression) { // The method must be called Contains and must return bool if (expression.Method.Name != "Contains" || expression.Method.ReturnType != typeof(bool)) return false; var list = expression.Object; Expression operand; if (list == null) { // Static method // Must be Enumerable.Contains(source, item) if (expression.Method.DeclaringType != typeof(Enumerable) || expression.Arguments.Count != 2) return false; list = expression.Arguments[0]; operand = expression.Arguments[1]; } else { // Instance method // Exclude string.Contains if (list.Type == typeof(string)) return false; // Must have a single argument if (expression.Arguments.Count != 1) return false; operand = expression.Arguments[0]; // The list must be IEnumerable<operand.Type> if (!typeof(IEnumerable<>).MakeGenericType(operand.Type).IsAssignableFrom(list.Type)) return false; } // Try getting the list items object listValue; if (list.NodeType == ExpressionType.Constant) // from constant value listValue = ((ConstantExpression)list).Value; else { // from constant value property/field var listMember = list as MemberExpression; if (listMember == null) return false; var listOwner = listMember.Expression as ConstantExpression; if (listOwner == null) return false; var listProperty = listMember.Member as PropertyInfo; listValue = listProperty != null ? listProperty.GetValue(listOwner.Value) : ((FieldInfo)listMember.Member).GetValue(listOwner.Value); } var listItems = listValue as System.Collections.IEnumerable; if (listItems == null) return false; // Do whatever you like with listItems return true; } Point p = c;对象转换为Point (actually, slices the object to Point)并调用Point类的默认赋值运算符。默认赋值运算符将所有值(以及私有数据)复制到新对象。

查看更多Copy constructors, assignment operators, and exception safe assignment

答案 3 :(得分:0)

您无法通过Derived类访问私有成员,当您调用display()函数(属于Point类)时,它可以显示x和y。当您假设Point p = c并调用p.display()时,它仍然会调用Pointer类的方法。因为Circle可以看到她的父母&#39; display()方法。将您的display()方法设为私有,Circle无法调用它。

答案 4 :(得分:0)

Point成员可以在Point的{​​{1}}子对象中“访问”。

由于您没有为Circle定义复制构造函数,因此复制Point的行为如下:

Point

并且由于Point(const Point& p) : x(p.x), y(p.y) {} 继承自CirclePoint可以转换为c,因此const Point&可以复制Point p = c; Point子对象{1}}。
这被称为“对象切片”。

(在一个不相关的说明中,“一个圆圈是一种点”是一种奇怪的关系。)

答案 5 :(得分:0)

在这一行

Point p = c;

您正在调用Point的复制构造函数:

Point::Point(const Point& p)

因为您可以从Derived类创建对Base类的引用,所以您的代码等同于:

Point &ref = c;
Point p = ref;

现在p将包含Circle Point部分的副本。

因为您在Point构造函数中初始化了Circle Circle个对象的一部分,如下所示:

Circle::Circle(float a, float b, float r) :Point(a, b), radius(r) {}
调用

Point(a,b)构造函数,它将使用参数PointCircle初始化a部分b