C++、C#父类子类互转机制

简单来说子类可以直接转换为父类,但是父类如果想转换为子类是有条件的,首先被转换的父类对象起初必须声明为相同的子类对象,也就是说首先是某种子类对象转换来的父类对象可以在转换回去。C#的转换机制比较简单,对于父类、子类没有什么特殊要求,但是C++要求父类必须是含有虚函数的类(实现了多态机制),才能有条件实现父类转为子类。下面用代码说明
C#代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace inheritCS
{
    public class person
    {
        public string name;
        public int age;
    }

    class student : person
    {
        public string school;
        public int grade;
    }

    class teacher : person
    {
        public string subject;
    }
    class Program
    {
        static void Main(string[] args)
        {
            student stu = new student();
            stu.name = "pupil";
            stu.school = "school1";
            stu.grade = 2;
            stu.age = 10;

            teacher t = new teacher();
            t.name = "teacher";
            t.age = 30;
            t.subject = "maths";

            person p1 = stu as person;
            if(p1!=null)
            {
                Console.WriteLine(string.Format("{0} 由 student 转 person 成功", stu.name));
            }
            else
            {
                Console.WriteLine(string.Format("{0} 由 student 转 person 失败", stu.name));
            }
            person p2 = t as person;
            if (p2 != null)
            {
                Console.WriteLine(string.Format("{0} 由 teacher 转 person 成功", t.name));
            }
            else
            {
                Console.WriteLine(string.Format("{0} 由 teacher 转 person 失败", t.name));
            }
            
            student stuReceiver = p1 as student;
            if (stuReceiver != null)
            {
                Console.WriteLine(string.Format("{0} 由 person 转 student 成功", p1.name));
            }
            else
            {
                Console.WriteLine(string.Format("{0} 由 person 转 student 失败", p1.name));
            }

            stuReceiver = p2 as student;
            if (stuReceiver != null)
            {
                Console.WriteLine(string.Format("{0} 由 person 转 student 成功", p2.name));
            }
            else
            {
                Console.WriteLine(string.Format("{0} 由 person 转 student 失败", p2.name));
            }
            if (Console.ReadKey(true).Key == ConsoleKey.Enter)
            {
                return;
            }
        }
    }
}

执行结果如下图。这里person是父类,student、teacher是子类,student、teacher转person完全没问题,student转化为的父类对象可以成功转换回student,但是teacher转化为的父类对象无法转换为student
在这里插入图片描述
C++代码

// inheritCPP.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdlib.h>
#include <string.h>

class person 
{
public:
	char name[10];
	int age;
	virtual void Show() { printf("This is Base calss"); }
};

class student :public person
{
public:
	char school[10];
	int grade;
};

class teacher :public person
{
public:
	char subject[10];
};


int main()
{
	student stu;
	strcpy_s(stu.name, "pupil");
	strcpy_s(stu.school, "school1");
	stu.grade = 2;
	stu.age = 10;

	teacher t;
	strcpy_s(t.name, "teacher");
	t.age = 30;
	strcpy_s(t.subject, "maths");

	person* p1 = NULL;
	person* p2 = NULL;
	student* stuReceiver;

	if ((p1 = &stu) != NULL)
	{
		printf("%s 由 student 转 person 成功\n", stu.name);
	}
	else
	{
		printf("%s 由 student 转 person 失败\n", stu.name);
	}
	if ((p2 = &t) != NULL)
	{
		printf("%s 由 teacher 转 person 成功\n", t.name);
	}
	else
	{
		printf("%s 由 teacher 转 person 失败\n", t.name);
	}

	if (stuReceiver = dynamic_cast<student*>(p1))
	{
		printf("%s 由 person 转 student 成功\n",p1->name);
	}
	else
	{
		printf("%s 由 person 转 student 失败\n", p1->name);
	}

	if (stuReceiver = dynamic_cast<student*>(p2))
	{
		printf("%s 由 person 转 student 成功\n", p2->name);
	}
	else
	{
		printf("%s 由 person 转 student 失败\n", p2->name);
	}
	getchar();
    return 0;
}


整体思路和C#一样,但是实现时父类必须含有虚函数已实现多态机制,这样才能实现有条件的父类转换为子类,执行结果如下图
在这里插入图片描述

<think>嗯,用户现在问的是C#中如何通过强制型转换来调用父类子类的方法或属性。之前他们问过关于C++中使用vector存储基子类的问题,现在转向C#,可能是在学习不同语言中的继承和多态实现。 首先,我需要回顾用户提供的引用内容。引用1到4都是关于C#中的型转换,包括隐式转换、强制转换、as和is操作符的使用。用户现在希望得到具体的示例,展示如何通过强制转换来调用方法或属性。 用户的上一个问题涉及C++中的多态和智能指针,而这次是C#,所以需要确保回答符合C#的语法和特性。C#中的型转换和C++有所不同,特别是as和is关键字的使用,以及装箱拆箱的问题,但用户的问题主要集中在继承体系中的转换。 接下来,我需要确定用户的需求层次。他们可能已经了解基本的继承概念,但需要具体示例来理解如何正确地进行型转换以访问子类父类的成员。可能需要区分向上转型和向下转型,以及安全转换的方法。 用户提供的引用中提到,子类隐式转换为父类(向上转型),而父类转换为子类需要显式转换(向下转型),可能失败,所以需要as或is来检查。引用3中的示例展示了强制转换和as的使用,以及可能的错误情况。 因此,回答中需要包含以下几点: 1. 定义基和派生,展示方法重写。 2. 向上转型的隐式转换,调用父类引用的方法。 3. 向下转型的显式转换,使用强制转换或as操作符,并处理可能的情况。 4. 使用is进行型检查,确保转换安全。 5. 示例代码演示这些情况,并说明注意事项,如InvalidCastException。 需要注意用户可能混淆C++C#的转换机制,比如C++中的dynamic_cast和C#中的as操作符的区别。同时,要强调在C#中,as操作符转换失败返回null,而不是抛出异常,而强制转换则会抛出异常。 用户可能还想知道如何访问子类特有的属性和方法,这需要向下转型后才能调用。例如,在基引用指向子类对象时,如何调用子类独有的方法。 需要确保示例代码正确,比如基中的方法是否为虚方法,子类是否重写,或者在隐藏方法时使用new关键字。例如,引用3中的Animal没有虚方法,但用户的问题中提到调用方法,可能需要使用虚方法和override,或者使用new关键字隐藏基方法。 另外,用户的问题中提到“强制型转换调用父类子类的方法或属性”,可能需要说明即使使用父类引用,如果实际对象是子类,并且方法被重写,调用虚方法时会执行子类的方法,而无需转换。但若要调用子类特有的方法,则必须进行转换。 最后,总结注意事项,比如正确使用as和强制转换,处理可能的null或异常,以及使用is进行型检查的重要性。</think>在C#中通过型转换调用父类/子类方法和属性,需要结合继承关系与转换操作。以下是具体实现方案和示例: --- ### 一、基础定义 ```csharp // 基 class Animal { public virtual void Eat() => Console.WriteLine("动物进食基础方法"); } // 派生 class Cat : Animal { public override void Eat() => Console.WriteLine("猫吃鱼"); // 重写基方法 public void Purr() => // 子类特有方法 Console.WriteLine("呼噜声~"); } // 派生2 class Dog : Animal { public new void Eat() => // 隐藏基方法 Console.WriteLine("狗啃骨头"); public void Bark() => Console.WriteLine("汪汪叫"); } ``` --- ### 二、向上转型调用(隐式转换) ```csharp Animal animal1 = new Cat(); // 隐式转换 animal1.Eat(); // 输出"猫吃鱼"(多态调用) Animal animal2 = new Dog(); animal2.Eat(); // 输出"动物进食基础方法"(方法隐藏) ``` --- ### 三、向下转型调用(显式转换) #### 方案1:直接强制转换(可能抛出异常) ```csharp if (animal1 is Cat) { Cat realCat = (Cat)animal1; // 强制转换 realCat.Purr(); // 调用子类特有方法 } // 危险示例(会抛出InvalidCastException) // Dog invalidDog = (Dog)animal1; ``` #### 方案2:as运算符(安全转换) ```csharp Dog maybeDog = animal2 as Dog; if (maybeDog != null) { maybeDog.Bark(); // 输出"汪汪叫" maybeDog.Eat(); // 输出"狗啃骨头" } ``` --- ### 四、混合型转换示例 ```csharp List<Animal> zoo = new List<Animal> { new Cat(), new Dog(), new Cat() }; foreach (var animal in zoo) { // 通用方法调用 animal.Eat(); // 特定型处理 if (animal is Cat c) { // C#7模式匹配 c.Purr(); } else if (animal is Dog d) { d.Bark(); } } ``` --- ### 五、属性访问示例 ```csharp class Vehicle { public int Wheels { get; set; } = 4; } class Car : Vehicle { public string Brand { get; set; } = "未知"; } Vehicle v = new Car(); Console.WriteLine(v.Wheels); // 直接访问基属性 if (v is Car c) { Console.WriteLine(c.Brand); // 访问子类特有属性 } ``` --- ### 关键差异总结 | 转换型 | 语法 | 失败处理 | 适用场景 | |----------------|----------------|----------------|--------------------------| | 隐式向上转换 | `Parent p = child` | 自动成功 | 多态基础操作 | | 强制向下转换 | `(Child)parent` | 抛出异常 | 确定型时使用 | | as运算符 | `parent as Child` | 返回null | 安全型检测场景 | | is模式匹配 | `parent is Child c`| 返回布尔值 | C#7+现代代码推荐方式 | --- ### 注意事项 1. **虚方法重写**:使用`override`实现多态调用[^3] 2. **方法隐藏风险**:`new`关键字会隐藏基方法,可能导致非预期行为 3. **型安全**:推荐优先使用`as`+null检查替代直接强制转换[^2] 4. **模式匹配优势**:C#7+的`is`模式匹配可简化代码(示例第四节) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值