在以下代码中,Circle
是Point
的公共继承,其中x
的私有成员y
,Point
无法访问。但是,在将Circle c
分配给Point p
时,我发现p
实际上可以为x
和y
获得正确的值。为什么会这样?
#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
答案 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)
您无权访问变量x
和y
,因为它们是私有的。但您可以访问公共方法display()
。 display()
是类Point
的公共方法,可以访问私有变量。
换句话说,您可以调用方法display()
,但无法直接访问私有变量x
和y
。
答案 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) {}
继承自Circle
,Point
可以转换为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)
构造函数,它将使用参数Point
和Circle
初始化a
部分b
。