标签: polymorphism

C++ 多态性和类型转换

我对 C++ 比较陌生,一直在使用 OpenGL 开发基本的 3D 渲染引擎。我有以下问题:我有一个名为 GeomEntity 的类,它是所有几何基元的基类。我有另一个名为 DefaultMaterial 的类,它是所有材质的基类(由不同类型的着色器程序组成)。因为我将拥有多种类型的材质,例如:ColorMaterial、TextureMaterial、AnimatedMaterial 等,我需要在 GeomEntity 类中放置对材质的引用,以便从主应用程序我可以使用此功能设置任何材料:

  void GeomEntity ::addMaterial (const DefaultMaterial *mat){

         material=mat;////material is the member variable pointer of type DefaultMaterial

  }
Run Code Online (Sandbox Code Playgroud)

但问题是,虽然所有这些材质都派生自 DefaultMaterial,但它们都有自己独特的方法,如果我默认将它们引用到 DefaultMaterial 变量,则无法触发这些方法。例如在主应用程序中:

  Sphere sphere;
  ....
  sphere.addMaterial(&animMaterial);///of type AnimatedMaterial
  sphere.material->interpolateColor(timerSinceStart);
   ///doesn't happen anything  as the sphere.material is
  /// of type DefaultMaterial that has   no interpolateColor() method
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用模板或强制转换,但我想听听 C++ 中这种多态性的最佳实践。在 Java 或 C# 中,我真的会使用这样的东西:

((AnimatedMaterial)sphere.material).interpolateColor(timerSinceStart);
Run Code Online (Sandbox Code Playgroud)

c++ oop polymorphism

0
推荐指数
1
解决办法
6632
查看次数

这个方法是重载、重写还是无?

java中方法重载和重写的区别?没有给出正确答案。下面是java代码。

家长

public class Parent {
    void display() {
        // some code
    }
}
Run Code Online (Sandbox Code Playgroud)

儿童

public class child extends Parent
    void display(int a) {
        // some code
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:这个方法是重载、重写还是无?

java polymorphism overriding overloading

0
推荐指数
1
解决办法
146
查看次数

子类中的虚函数表是如何生成的

所以我知道在 C++ 中,虚拟方法适用于存储在表中的每个类,并且每个实例都有一个指向该表的指针。所以我的问题是子类表是什么样的。我将提供一个汇编指令:

vtable for Derived:
    .long   0
    .long   _typeinfo for Derived
    .long   _Derived::set()
    .globl  _vtable for Base
    .section    .rdata$vtable for Base,"dr"
    .linkonce same_size
    .align 4
Run Code Online (Sandbox Code Playgroud)

因此,从这里我可以看到 Derived 有一个虚拟方法set(),但令我烦恼的部分是 Base 的 vtable。Derived vptr 是否保存指向 Base vptr 的指针,还是存储在 Derived 的 vtable 内。我注意到,在代码中,编译器仅将 vtable 存储在对象的 0 地址处,一次存储在 Base 构造函数中,一次存储在 Derived 中。为什么vtable没有被覆盖?

PS我不太明白指令

编辑:

class Base{
   virtual void print() {
       printf("Base");
   }
}

class Derived : Base{
   virtual void print(){
       printf("Derived");
   }
}
Run Code Online (Sandbox Code Playgroud)

c++ polymorphism assembly vtable

0
推荐指数
1
解决办法
723
查看次数

如何为单一类型专门化(重载)函数的行为?

我正在使用 Real World Haskell,并且作为练习的一部分,我意识到我想要一个类似于 的函数show :: Show(a) => a -> String,但它不影响字符串(而不是转义引号)。在伪代码中,我想要的是:

show' :: String -> String
show' = id

show':: Show(a) => a -> String
show' = show
Run Code Online (Sandbox Code Playgroud)

显然这不起作用(ghc 抱怨多个类型签名和多个声明)。看来我应该改用类型类。当我尝试编写此代码时,编译器不断建议我添加更多语言扩展:

{-# LANGUAGE FlexibleInstances, UndecidableInstances, IncoherentInstances #-}

class Show' a where
  show' :: a -> String

instance Show' String where
  show' = id

instance (Show a) => Show' a where
  show' = show

-- x == "abc"
x = show' "abc"
y = show' 9
Run Code Online (Sandbox Code Playgroud)

起初,这似乎工作:x == "abc" …

polymorphism haskell typeclass

0
推荐指数
1
解决办法
79
查看次数

C ++中集合和多集之间的多态性

有没有办法使用多态来为集合和多集提供一个泛型?如下。

注意:但仅适用于集合,(set, multiset)

template<typename T>
void foo(parent_set<T> &s) {
    // do something
}
// main
set<int> s1 = {1, 2, 3, 4, 5};
foo(s1);
multiset<int> s2 = {1, 2, 2, 2, 2, 3};
foo(s2); 
Run Code Online (Sandbox Code Playgroud)

c++ polymorphism std set multiset

0
推荐指数
1
解决办法
45
查看次数

为什么类可以被视为 std::function&lt;float()&gt; 但 shared_ptr 不能被视为 std::shared_ptr&lt;std::function&lt;float()&gt;&gt;&gt;

有一些代码能够将实现operator()std::function. 然后我尝试做同样的事情,但使用shared_ptr

#include <functional>
#include <memory>

class WhiteNoise  {
public:
    WhiteNoise()  {}
    float operator() () {
        return 0;
    }
};

int main() {
    //fails
    std::shared_ptr<std::function<float()>> = std::dynamic_pointer_cast<std::function<float()>>(std::make_shared<WhiteNoise>());
    //fails
    std::shared_ptr<std::function<float()>> = std::make_shared<WhiteNoise>();
    //works
    std::function<float()> f = WhiteNoise();
}
Run Code Online (Sandbox Code Playgroud)

为什么我可以WhiteNoise当作std::function<float()>但不能shared_ptr<WhiteNoise>当作shared_ptr<std::function<float()>>

c++ polymorphism

0
推荐指数
1
解决办法
29
查看次数

使用抽象基类来强制模板参数类型的公共接口是一种不好的做法吗?

我是模板编程的新手,并且偶然发现了这个习惯用法。例如,类似:

class FooBase {
 public:
  virtual void do_something() = 0;
};

template <class Foo> // Foo is derived from FooBase
void g(Foo& foo) {
  static_assert(std::is_base_of<FooBase, Foo>::value);
  // ...
  foo.do_something();
  // ...
}
Run Code Online (Sandbox Code Playgroud)

在我看来,这种模式很有用,因为:

  1. 纯虚函数声明具有显式签名;与 C++20 概念requires子句(如果可用的话)相比,指定属性、参数和返回类型很容易。
  2. 这是很好的文档;只需阅读FooBase标头即可清楚定义新 Foo 类的要求。
  3. 可以将所有 Foo 的通用功能重构到同一个FooBase类中。

但是我担心使用的性能影响virtual函数对性能的影响。我的理解是运行时没有成本,因为该函数是从派生类调用的;但链接器将无法内联该函数。

另一个缺点是不允许虚拟模板功能。

最后,我担心这可能是一种代码味道,因为它使用运行时多态性功能来执行静态检查。C++20 概念可能是执行此操作的“正确”方法,但由于上述三个原因,它们似乎不太方便。

c++ polymorphism templates c++-concepts

0
推荐指数
1
解决办法
253
查看次数

如果只有某些派生类是多态的,基类析构函数是否需要是虚拟的?

我与这个问题有类似的情况,我有两个共享公共接口函数的类,因此我将该函数(示例中的manage_data_in_memory())拉出到这两个类继承的基类中。然而,这两个类在其他方面并不相关,其中一个是多态的,而另一个则不是。也不希望有人声明这个基类的对象,因为它的存在只是为了防止代码重复(有办法强制执行吗?我知道纯虚函数可以防止对象被实例化,但是声明一个虚拟函数在派生类中不执行任何操作的纯虚拟似乎是糟糕的设计)。

在这种情况下,基类析构函数是否需要是虚拟的?这将迫使其他派生类也有一个它不需要的虚拟析构函数。谢谢。

所以现在我的代码格式为

class base  {  // don't instantiate an object of this, is there a way to enforce this?
 public: 
   void manage_data_in_memory();
 protected:
    data;        
 };
    
 class derived : public base
 {
 public:
    void sendData();
 private:
     virtual void sendDataHelper(); // override this in derived classes which need to send custom data in addition to the default data
 };
    
 class derived2 : public base
 { 
  public:
   void do_Z_On_data()
 };
Run Code Online (Sandbox Code Playgroud)

c++ polymorphism

0
推荐指数
1
解决办法
135
查看次数

没有对象切片的多态向量 [C++]

我试图在一个std::array(或任何其他容器)中存储从基类派生的许多对象,而无需对象切片。

下面的代码片段所需的输出是:

Hi from child1!
Hi from child2!
Run Code Online (Sandbox Code Playgroud)

和代码:

Hi from child1!
Hi from child2!
Run Code Online (Sandbox Code Playgroud)

我实际从代码中得到的输出是:

This shouldn't print
This shouldn't print
Run Code Online (Sandbox Code Playgroud)

显然派生对象已被切片。有什么办法可以避免这种情况吗?

预先感谢您提供的任何建议。

c++ polymorphism containers

0
推荐指数
1
解决办法
177
查看次数

C++ 如何从不带头文件的不同文件扩展类

我\xe2\x80\x99m 尝试执行基本的多态性程序,但遇到了一些问题。\n我有 2 个文件,Currency.cpp 和 Dollar.cpp

\n

货币.cpp 看起来像这样

\n
#include <iostream>\nusing namespace std;\nclass Currency{\n/* code */\n};\n
Run Code Online (Sandbox Code Playgroud)\n

Dollar.cpp 看起来像这样

\n
#include <iostream>\nusing namespace std;\nclass Dollar : protected Currency{\n/* code /*\n};\n
Run Code Online (Sandbox Code Playgroud)\n

当我尝试在文件之间构建路径(在 mac 上使用命令 shift b)时,它告诉我货币不被识别为类(在 Dollar.cpp 中)。I\xe2\x80\x99m 不应该使用头文件,因为这是用于指定的分配。我应该做些什么?

\n

我在 2020 m1 Mac 上使用 vs code,如果这与它有任何关系的话

\n

编辑:\n感谢所有反馈。据我所知,我在这里问的是不可能的。这个作业是针对接受多种语言的数据结构和算法课,所以可能老师对c++之类的生疏了。我只需要使用头文件,教授就需要处理它,哈哈。

\n

c++ polymorphism inheritance

0
推荐指数
1
解决办法
465
查看次数