c++ 形参是子类的引用,实参却是父类对象
时间: 2024-09-18 21:06:46 浏览: 39
在 C++ 中,当形参是子类类型的引用,并且函数接受的是父类类型的指针或引用作为实参时,这被称为“隐式转换”或“上下文依赖类型”。这是由于 C++ 的动态绑定特性,也称为晚期绑定或运行时多态。
例如:
```cpp
class Base {
public:
virtual void print() { std::cout << "Base" << std::endl; }
};
class Derived : public Base {
public:
void print() override { std::cout << "Derived" << std::endl; }
};
void function(Base& baseRef) {
// 实参是一个 Derived 对象
Derived derived;
// 虽然形参是 Base 类型的引用,但因为是通过 derived 引用传递,会调用 Derived 类的 print 方法
baseRef.print(); // 输出 "Derived"
}
int main() {
Derived derived;
function(derived); // 隐式转换,不会引发错误,运行时调用的是 Derived 的 print 方法
return 0;
}
```
相关问题
c++ 形参是父类的引用,实参却是子类对象
在 C++ 中,当形参是父类的引用,而实参是子类的对象时,这种情况称为“向下转型”或“隐式转换”。这是因为尽管函数声明中使用的形参是父类类型的,但在实际调用时,如果传入的是子类的对象,编译器会自动将子类对象转换为父类类型的指针或引用。
例如,假设有一个基类 `Shape` 和两个派生类 `Circle` 和 `Square`:
```cpp
class Shape {
public:
virtual void draw() const { cout << "Drawing a shape." << endl; }
};
class Circle : public Shape {
public:
void draw() const override { cout << "Drawing a circle." << endl; }
};
class Square : public Shape {
public:
void draw() const override { cout << "Drawing a square." << endl; }
};
void printShape(const Shape& s) {
s.draw();
}
int main() {
Circle circle;
Square square;
// 尽管printShape接受的是Shape的引用,但circle和square都是其子类对象
printShape(circle); // 输出: Drawing a circle.
printShape(square); // 输出: Drawing a square.
return 0;
}
```
这里,`printShape` 函数可以接受任何 `Shape` 类型的引用,而当我们传入 `Circle` 或 `Square` 对象时,它们的 `draw` 方法会被正确地调用,体现了 C++ 的多态性。
从变量的初始化、对象的创建方式、局部变量是否可以重定义、变量名和方法名是否可重名、继承方式(单、多重)、默认形参、运算符重载、参数传递方式、构造函数/拷贝构造函数、析构函数、常量的表示const/final、有一个对象(数组)为另一个对象(数组)变量赋值、访问控制方式及默认方式这十三个方面比较Java与C++,每个方面描述详细,1000个字
1. 变量的初始化:在Java中,所有变量都有默认值,即使没有显式初始化,变量也会被赋予一个默认值,这是Java语言的特性之一。而在C++中,变量没有默认值,如果不显式进行初始化,则变量的值是未定义的。在Java中,可以使用构造函数来初始化对象,构造函数是一种特殊的方法,用于创建并初始化对象。而在C++中,可以使用构造函数或初始化列表来初始化对象。
2. 对象的创建方式:在Java中,对象只能通过new关键字来创建,new关键字会在堆上分配内存并返回一个对该对象的引用。而在C++中,可以使用new关键字或者直接声明一个对象来创建对象。如果使用new关键字,则会在堆上分配内存并返回一个指向该对象的指针。
3. 局部变量是否可以重定义:在Java中,局部变量不能被重定义,即在同一个作用域内不能定义同名的局部变量。而在C++中,可以在同一作用域内定义多个同名的局部变量。
4. 变量名和方法名是否可重名:在Java中,变量名和方法名不能重名,即在同一个作用域内不能定义同名的变量和方法。而在C++中,变量名和方法名可以重名,但是在同一个作用域内只能存在一个定义。
5. 继承方式(单、多重):Java只支持单继承,即一个类只能继承自一个父类。而C++支持单继承和多重继承,即一个类可以同时继承多个父类。
6. 默认形参:Java中不支持默认形参,即在函数定义时不能指定形参的默认值。而C++支持默认形参,即在函数定义时可以指定形参的默认值,如果在调用函数时没有传递实参,则使用默认值作为实参。
7. 运算符重载:Java不支持运算符重载,即不能通过重载运算符来改变运算符的含义。而C++支持运算符重载,即可以通过重载运算符来改变运算符的含义。
8. 参数传递方式:Java只支持按值传递,即将实参的值复制给形参,形参和实参是两个独立的变量。而C++支持按值传递和按引用传递,按值传递与Java相同,而按引用传递则将实参的地址传递给形参,形参和实参指向同一个变量。
9. 构造函数/拷贝构造函数/析构函数:Java中只有构造函数,构造函数是一种特殊的方法,用于创建并初始化对象。而C++中有构造函数、拷贝构造函数和析构函数。拷贝构造函数用于将一个对象拷贝到另一个对象中,析构函数用于释放对象占用的资源。
10. 常量的表示const/final:Java中使用final关键字表示常量,即使用final修饰的变量在初始化后不能被修改。而C++中使用const关键字表示常量,即使用const修饰的变量也在初始化后不能被修改。
11. 有一个对象(数组)为另一个对象(数组)变量赋值:在Java中对象和数组都是引用类型,因此可以通过引用来进行赋值操作。例如,可以将一个数组的引用赋值给另一个数组变量。而在C++中,如果要将一个数组赋值给另一个数组变量,需要使用memcpy函数来进行复制。
12. 访问控制方式及默认方式:Java中使用访问控制符(public、private、protected)来限制对类成员的访问,public表示可访问,private表示不可访问,protected表示只有子类可以访问。默认访问控制符是包访问控制符,即同一个包内的类可以访问。而C++中使用访问说明符(public、private、protected)来限制对类成员的访问,public表示可访问,private表示不可访问,protected表示只有子类和派生类可以访问。默认访问控制符是私有访问控制符,即同一个类内的成员可以访问。
13. 总体来说,Java和C++在语法和语义上有很多相似之处,但是也存在着一些不同之处,这些不同之处可能会对程序的实现方式和结果产生影响。例如,在Java中,由于所有变量都有默认值,因此可以减少程序员的工作量,但也会增加程序的安全隐患。而在C++中,由于支持运算符重载和多重继承等特性,可以提高程序的灵活性和扩展性,但也会增加代码的复杂度和难度。
阅读全文