animal

多态中的虚析构函数

只愿长相守 提交于 2019-11-29 00:17:38
为什么析构函数要声明成virtual呢? 因为,如果delete一个基类的指针时, 如果它指向的是一个子类的对象,那么析构函数不为虚就会导致无法调用子类析构函数,从而导致资源泄露。 如果一个类要被使用成 多态 的,那么这个 virtual是必须 的。比如: #include <iostream> using namespace std; class Animal { char* ap; public: Animal() { ap = new char; std::cout << "Animal ctor" << std::endl; } virtual void foo() { std::cout << "Animal::foo" << std::endl; } virtual ~Animal() { std::cout << "Animal dtor" << std::endl; delete ap; } }; class Dog : public Animal { char* dp; public: Dog() { dp = new char; std::cout << "Dog ctor" << std::endl; } virtual void foo() { std::cout << "Dog::foo" << std::endl; } virtual ~Dog() {

C#基础--虚方法与重写

孤者浪人 提交于 2019-11-28 12:25:31
作用:子类可以对父类重写,虚方法是对多态特征体现。 1 public class Animal 2 { 3 public string Name { get; set; } 4 public virtual void Eat() 5 { 6 Console.WriteLine("{0}正在吃草",Name); 7 } 8 9 } 10 public class Sheep : Animal 11 { 12 public Sheep(){ Name = "羊"; } 13 public override void Eat() 14 { 15 base.Eat(); 16 Console.WriteLine("吃草"); 17 18 } 19 20 } 21 22 public class Tigger : Animal 23 { 24 public Tigger() { Name = "老虎"; } 25 public override void Eat() 26 { 27 base.Eat(); 28 Console.WriteLine("老虎吃羊"); 29 30 } 31 } Animal animal1 = new Sheep(); Animal animal2 = new Tigger(); animal1.Eat(); animal2.Eat();    来源:

C#基础-037 里氏转换

纵然是瞬间 提交于 2019-11-27 18:06:43
class Animal { private string name; private int age; private char gender; public string Name { get { return name; } set { name = value ; } } public int Age { get { return age; } set { age = value ; } } public char Gender { get { return gender; } set { gender = value ; } } public Animal () { } public Animal ( string name, int age, char gender) { this .Name = name; this .Age = age; this .Gender = gender; } public void Eat () { Console.WriteLine( "吃" ); } } class Dog:Animal { public Dog ( string name, int age, char gender): base (name,age,gender) { } public void Bark () { Console.WriteLine( "吠" )

Python面向对象学习

北城余情 提交于 2019-11-27 13:57:13
以下面例子作为面向对象基础介绍,类比java里的面向对象既可以,大同小异 class Employee(): raiseAmount=1.04 employeeNum=0 def __init__(self,first,surname,salary):#相当于java里面的结构体,self可以理解为this self.first = first #属性 self.surname = surname self.salary = salary self.email = first + '.' + surname + '@163.com' Employee.employeeNum+=1 def infosummary(self):#方法 return '{}, {}, {}'.format(self.first + " " + self.surname, self.salary, self.email) def raiseSalary(self): self.salary = self.salary * self.raiseAmount employee1 = Employee('Harray','Potter',4000)#声明一个实例 employee2 = Employee('peter','lee',5000) print(employee2.infosummary())

python基础--面向对象之继承

烂漫一生 提交于 2019-11-27 13:51:14
# 继承是一种创建新类的方式,新建的类可以继承一个,或者多个父类, # 父类又可以称为基类或者超类,新建的类可以称为派生类,子类 class ParentClass1: # 定义父类 1 pass class ParentClass2: # 定义父类 2 pass class SubClass1(ParentClass1): # 继承一个父类 pass class SubClass2(ParentClass1,ParentClass2): # 继承两个父类 pass print(SubClass1.__bases__) # 查看父类 print(SubClass2.__bases__) class Animal: def eat(self): print("%s is eating" %self.name) def drink(self): print("%s is drinking" % self.name) def shit(self): print("%s is shiting" %self.name) def pee(self): print("%s is peeing" %self.name) # 子类可以使用父类的函数属性和数据属性 class Cat(Animal): def __init__(self,name): self.name = name self

46 python - self

泄露秘密 提交于 2019-11-27 12:58:25
看如下示例: # 定义一个类 class Animal : # 方法 def __init__ ( self , name ) : self . name = name def printName ( self ) : print ( '名字为:%s' % self . name ) # 定义一个函数 def myPrint ( animal ) : animal . printName ( ) dog1 = Animal ( '西西' ) myPrint ( dog1 ) dog2 = Animal ( '北北' ) myPrint ( dog2 ) 运行结果: 总结 所谓的self,可以理解为自己 可以把self当做C++中类里面的this指针一样理解,就是对象自身的意思 某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可 来源: https://blog.csdn.net/qq_20042935/article/details/99678788

C#泛谈 —— 变体(协变/逆变)

穿精又带淫゛_ 提交于 2019-11-27 04:40:14
有如下四个类。 public class Animal { } public class Mammal : Animal { } public class Dog : Mammal { public void EatBone() { } } public class Panda : Mammal { public void EatBamboo() { } } Animal animal = new Dog() ; 这样的赋值肯定是没问题的,但这只是 多态。 变体的大概意思是:有T和U两个类型,并且T = U (此处的等号为 赋值 )成立,如果T和U经过某种操作之后分别得到T’和U’,并且T’ = U’也成立,则称此 操作 为协变;如果U’ = T’,则称此操作为逆变。 //以下代码能通过,则说明Operation是协变。 T = U; // =表示赋值 ↓ Operation(T) = Operation(U); //类似的,以下操作为逆变。 T = U; ↓ Operation2(U) = Operation2(T); 一、特殊的协变——数组 我们常说协变和逆变是.net 4.0中引入的概念,但实际上并不是。其实只要符合上面定义的,都是变体。我们先来看一个.net 1.0中就包含的一个协变: Animal[] animalArray = new Dog[ 10 ]; 这个 不是

抽象类与归一化

送分小仙女□ 提交于 2019-11-27 02:10:54
import abcclass Animal(metaclass=abc.ABCMeta): # 只能被继承,不能被实例化 @abc.abstractmethod def run(self): pass @abc.abstractmethod def eta(self): passclass Pople(Animal): def run(self): print('Pople is runing') def eta(self): print('Pople is etaing')class Pig(Animal): def run(self): print('Pig is runing ') def eta(self): print('Pig is etaing')class Dog(Animal): def run(self): print('Dog is runing ') def eta(self): print('Dog is etaing')pople1 =Pople()pig1 = Pig()dog1 = Dog() 来源: https://www.cnblogs.com/kingforn/p/11337643.html

不同类型的指针

爷,独闯天下 提交于 2019-11-27 01:21:57
1、思考,不同类型的指针,到底有什么区别?   指向Animal的指针和指向Dog的指针,到底有什么区别?首先,指针的表示方法相同,指针的内容相同,都是一个int,表示地址。区别只是指向对象的类型不同(好像是废话)。这有什么意义呢? 这其实是告诉了编译器如何解释这个地址中的内存内容以及大小。也就是说,对于指向Animal 的指针,编译器把指向内容当作一个Animal,对于指向Dog 指针,编译器把指向的内容当作Dog。 2、那么,问题来了,Animal* pa = new Dog(),是怎么做到运行期多态的呢?   pa的表面类型是Animal,真实类型是Dog,编译器在编译时只知道pa的表面类型,那么把pa当作Animal来解释,能不能做到运行时多态呢?简单回忆一下,Animal对应一个虚方法表(虚方法表可认为一个数组,元素是方法指针),Dog对应一个虚方法表,可以认为Dog中的虚方法表是整体拷贝了Animal 的虚方法表,对于重写的方法在对应的位置换上重写后的方法,对于新增的虚方法,加在虚方法表的最后。对象的内存中只有实例字段和vptr,vptr指向vtbl(虚方法表),根据对应的方法,在vtbl对应的位置上,找到方法指针,进而找到方法。   对于Animal对象和Dog对象,可认为在相同位置都放着vptr。这样的话,pa指向内存中的一个Dog对象