社区首页 >问答首页 >使用`dynamic_cast`来推断在基类上定义并在派生类上实现的成员函数的参数类型是否正确?

使用`dynamic_cast`来推断在基类上定义并在派生类上实现的成员函数的参数类型是否正确?
EN

Stack Overflow用户
提问于 2016-09-20 07:30:28
回答 1查看 97关注 0票数 1

我只是从C++开始。我正在尝试为向量运算的子集设计一个类(接口)。此抽象基类定义为:

代码语言:javascript
代码运行次数:0
复制
//file: vect.hh
#ifndef _vect_hh
#define _vect_hh
class vect
{
  public:
      virtual double norm() const = 0;
      virtual void   add(const double scaleThis, const double scaleOther,
                         const vect& other)  = 0;
      virtual double dot(const vect& other) const = 0;
      virtual vect* clone() const = 0;
      virtual vect* copy(const vect& other) const = 0;
      virtual ~vect()=default;
};
#endif

问题出现在参数为const vect& other的函数中。因为在派生类中,我真正想要的是像const vectDerived& other这样的参数。为了举例说明这个问题,我使用原始指针对上一个类做了一个简单的实现。因为我还有其他一些问题要在这个问题的末尾发表意见,所以我插入了这个类的完整定义。但请记住,最重要的函数是dotadd

代码语言:javascript
代码运行次数:0
复制
// file: vectDouble.hh
#ifndef _vectDouble_hh
#define _vectDouble_hh
#include <cmath>
#include <cstring>

#include "vect.hh"

class vectDouble: public vect
{
public:
    explicit vectDouble(const int n): n{n}, elem{new double[n]}
    {
        std::memset(elem,'\0',sizeof(double)*n);
    }
    ~vectDouble() override {delete[] elem;}
    vectDouble(const vectDouble& other): n{other.n}, elem{new double[n]}
    {
        std::memcpy(elem, other.elem, n*sizeof(double));
    }
    vectDouble& operator=(const vectDouble& other)
    {
        if(&other != this){
            delete[] elem; n = other.n;
            elem = new double[n];
            std::memcpy(elem, other.elem, sizeof(double)*n);
        }
        return *this;
    }
    vectDouble(vectDouble&& other): n{0}, elem{nullptr}
    {
        fillClass(other, *this);
    }
    vectDouble &operator=(vectDouble&& other)
    {
        if(&other != this){
            delete[] elem;
            fillClass(other, *this);
            other.elem = nullptr; other.n = 0;
        }
        return *this;
    }
    double norm() const override
    {
        double norm = 0.0;
        for(int i=0;i<n;i++){norm += elem[i]*elem[i];}
        return std::sqrt(norm);
    }
    double dot(const vect& other) const override
    {
        const vectDouble &v = dynamic_cast<const vectDouble&>(other);
        double dot = 0.0;
        for(int i=0;i<n;i++){dot += elem[i]*v.elem[i];}
        return dot;
    }
    void add (const double scaleThis, const double scaleOther,
          const vect& other) override
    {
        const vectDouble &v = dynamic_cast<const vectDouble&>(other);
        for(int i=0;i<n;i++){
                elem[i] = scaleThis*elem[i] + scaleOther*v.elem[i];
        }
    }
    double& operator[](const int i){return elem[i];}
    const double& operator[](const int i) const {return elem[i];}
    int size() const{return n;}
    vectDouble* clone() const override
    {
        return new vectDouble(*this);
    }
    vectDouble* copy(const vect& other) const override
    {
        const vectDouble &v = dynamic_cast<const vectDouble&>(other);
        auto *t = new vectDouble(*this);
        t->n = v.n;
        std::memcpy(t->elem, v.elem, t->n*sizeof(double));
        return t;
    }
private:
    void fillClass(const vectDouble& in, vectDouble& out)
    {
        out.n = in.n; out.elem = in.elem;
    }
    int    n;
    double *elem;
};
#endif

在这两个函数中,我使用const vectDouble &v = dynamic_cast<const vectDouble&>(other);将基类引用转换为具有派生类类型的引用。这是dynamic_cast的有效用例。如果不是,怎样才能达到这个效果呢?

我已经说过,我遇到了其他问题(很抱歉偏离了主要问题)。作为使用抽象类和前面实现的示例,我制作了这个简单但有点做作的主程序:

代码语言:javascript
代码运行次数:0
复制
    // file main.cc
#include <iostream>
#include <memory>
#include "vectDouble.hh"

double lsfit(const vect& dobs, const vect& dcalc)
{
    std::unique_ptr<vect> tmp(dcalc.copy(dcalc));

    return (dobs.dot(dcalc))/(dcalc.dot(*tmp));
}

void testFit()
{
    vectDouble d{10};
    vectDouble x{10};

    for(int i=0;i<x.size();i++){
    d[i] = static_cast<double>(3*i);
    x[i] = static_cast<double>(i);
    }
    std::cout<<"alpha="<<lsfit(d, x)<<std::endl;
}

int main()
{
    testFit();
    return 0;
}

这个程序演示了为所描述的接口设想的一个用例。但是,如果不使用std::unique_ptr,就会出现内存泄漏(使用g++compiler中的选项-fsanitize=leak进行识别)。如果我想手动管理内存(出于好奇心),而不是使用unique_ptr,那么清理此结果的正确方法是什么?可以直接从复制函数返回一个std::unique_ptr。当我尝试这样做时,我收到了与错误的协变返回类型相关的错误消息。

备注: 1)此接口的目的是抽象用于表示数组的存储方案,例如文件而不是内存中的表示。2)我意识到所呈现的复制功能更类似于创建/克隆加复制功能。3)如果将来我想在基类和派生类中都使用模板,那么所呈现的结构是足够的?例如template<float> class vect{...}template <float> class vectDerived{...}

遵循@hayt的建议,我更改了vect.hhvectDouble.hh的定义,以使用所描述的CRTP模式。在这些更改之后,我还将函数lsftit的定义更改为:

代码语言:javascript
代码运行次数:0
复制
template <class Derived> double lsfit2(const Derived& dobs, const Derived& dcalc)
{
    std::unique_ptr<Derived> tmp = dcalc.clone();
    Derived *t = tmp.get();
    t->copy(dcalc);
    return (dobs.dot(dcalc))/(dcalc.dot(*t));
}

在使用此模式时,这是定义此函数的正确方式吗?

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2016-09-20 08:01:51

你应该检查你是否真的需要继承,也许可以切换到一个带有模板参数的泛型向量类(从你只有"double“作为特定的东西)

另一种方法是将CRTP与声明接口结合使用。(我还在此参数中添加了unique_ptr )

代码语言:javascript
代码运行次数:0
复制
template <class Derived>
class vect
{
  public:
      virtual double norm() const = 0;
      virtual void   add(const double scaleThis, const double scaleOther,
                         const Derived& other)  = 0;
      virtual double dot(const Derived& other) const = 0;
      virtual std::unique_ptr<Derived> clone() const = 0;
      virtual std::unique_ptr<Derived> copy(const vect& other) const = 0;
      virtual ~vect()=default;
};

这样,你就有了相同的“接口”,但有了不同的“基类”,并且你的函数中也有了派生类。因此,您不必担心通过接口将“不兼容”的向量分配给彼此(请参阅dynamic_cast)。

此外,您可以稍后为进一步的规范派生该类。

下面是使用这种方法创建类时的样子:

代码语言:javascript
代码运行次数:0
复制
class vectDouble: public vect<vectDouble>
{
public:
    //...
    //NOTE: here vecDouble is a parameter. no need for dynamic casts
    double dot(const vectDouble& other) const override
    {        
        double dot = 0.0;
        for(int i=0;i<n;i++){dot += elem[i]*other.elem[i];}
        return dot;
    }
    void add (const double scaleThis, const double scaleOther,
          const vectDouble& other) override
    {

        for(int i=0;i<n;i++){
                elem[i] = scaleThis*elem[i] + scaleOther*other.elem[i];
        }
    }
    //also directly a unique pointer
    std::unique_ptr<vectDouble> clone() const override
    {
        return std::make_unique<vectDouble>(*this);
    }
    //...
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39588196

复制
相关文章
html 竖排导航条,html 导航栏
$(“#navbar a[href='{ { request.path }}’]”).parent().addClass(“active”)
全栈程序员站长
2022/09/01
3.7K0
案例:数控机床主轴校准与颤振监测系统
提高生产数量与产品质量始终是制造业努力追求的目标,工业4.0更勾勒出智能制造的美好愿景,促使被制造业视为是重要生产设备的CNC工具机(数控机床)也得因应这样的趋势不断地精益求精。而数控机床制造商在积极改善自家机器性能并提升加工精度以符合客户需求的过程中,机器校准正确与否是影响加工精度的重要因素之一。但一直以来制造业都是靠累积多年经验的老师傅来进行机器校准,工厂每日必须先以这种传统作法来检查设备才能正式开工;如果该厂需要制造的产品种类较多,每一次产线调整时还得再次为机器重新设定与校准。如此不科学的作业模式既繁琐又费时,一旦作业程序有所疏失就会发生加工精度失准的问题。
SHOUT
2022/05/31
2.9K0
案例:数控机床主轴校准与颤振监测系统
html导航栏纵向代码,html横向导航栏怎么做?横向导航条代码实例
有不少小伙伴在刚学习 html 的时候都会遇到这样一个问题:html 横向导航栏怎么做?今天W3Cschool小编就为大家分享一下简单的横向导航条代码,相信会对大家有所帮助。
全栈程序员站长
2022/09/02
6.3K0
【Flutter】底部导航栏实现 ( BottomNavigationBar 底部导航栏 | BottomNavigationBarItem 导航栏条目 | PageView )
Flutter 中的 Scaffold 组件实现了基础的材料设计 ( Material Design ) 可视化布局结构 ;
韩曙亮
2023/03/29
6.2K0
【Flutter】底部导航栏实现 ( BottomNavigationBar 底部导航栏 | BottomNavigationBarItem 导航栏条目 | PageView )
iOS小技能:自定义导航栏,设置全局导航条外观
在开发需求时app中使用的导航条在一个模块的主题基本是一致的,因此可通过自定义导航条来进行统一控制。
玖柒的小窝
2021/11/02
2.5K0
bootstrap 导航栏
<!doctype html> <html> <head> <meta charset="utf-8"> <title>联想控股</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="css/bootstrap.css" rel="stylesheet" type="text/css"> <script src="http://code.jquery.com/jquery.js"></script> <script src="js/bootstrap.min.js"></script> </head> <body> <nav class="navbar navbar-default" role="navigation"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#menu"> <span class="sr-only">展开导航</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">网站标题</a> </div> <div class="collapse navbar-collapse" id="menu"> <ul class="nav navbar-nav"> <li class="active"><a href="#">首页</a></li> <li><a href="#">导航标题1</a></li> <li><a href="#">导航标题2</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">下拉菜单 <b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="#">下拉菜单1</a></li> <li class="divider"></li> <li><a href="#">下拉菜单2</a></li> <li class="divider"></li> </ul> </li> </ul> </div> </nav> </body> </html>
用户5760343
2019/07/05
3.4K0
iOS 原生导航栏 修改导航栏文字颜色 大小
// 黑色导航栏 状态栏 self.navigationController.navigationBar.barStyle = UIBarStyleBlack; self.navigationController.navigationBar.barTintColor = [UIColor blackColor]; // 白色文字 // 中间title [self.navigationController.navigationBar setTitleTextAttributes:@{NSFontAttr
ppppy
2022/11/15
2.5K0
bootstrap affix 左侧栏导航栏
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Bootstrap 附加导航(Affix)插件</title> <link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script> <style> /* Custom Styles / ul.nav-tabs{ width: 140px; margin-top: 20px; border-radius: 4px; border: 1px solid #ddd; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.067); } ul.nav-tabs li{ margin: 0; border-top: 1px solid #ddd; } ul.nav-tabs li:first-child{ border-top: none; } ul.nav-tabs li a{ margin: 0; padding: 8px 16px; border-radius: 0; } ul.nav-tabs li.active a, ul.nav-tabs li.active a:hover{ color: #fff; background: #0088cc; border: 1px solid #0088cc; } ul.nav-tabs li:first-child a{ border-radius: 4px 4px 0 0; } ul.nav-tabs li:last-child a{ border-radius: 0 0 4px 4px; } ul.nav-tabs.affix{ top: 30px; / Set the top position of pinned element */ } </style> <script> ("#myNav").affix({ offset: { top: 125 } }); }); </script> </head> <body data-spy="scroll" data-target="#myScrollspy"> <div class="container"> <div class="jumbotron"> <h1>Bootstrap Affix</h1> </div> <div class="row"> <div class="col-xs-3" id="myScrollspy"> <ul class="nav nav-tabs nav-stacked" id="myNav"> <li class="active"><a href="#section-1">第一部分</a></li> <li><a href="#section-2">第二部分</a></li> <li><a href="#section-3">第三部分</a></li> <li><a href="#section-4">第四部分</a></li> <li><a href="#section-5">第五部分</a></li> </ul> </div> <div class="col-xs-9"> <h2 id="section-1">第一部分</h2> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu sem tempor, varius quam at, luctus dui. Mauris magna metus, dapibus nec turpis vel, semper malesuada ante. Vestibulum id metus ac nisl bibendum scelerisque non non purus. Suspendisse varius nibh non aliquet sagittis. In tincidunt orci sit amet elementum vestibulum. Vivamus fermentum in
用户5760343
2019/07/07
2.8K0
html+css网页开发 之 头部导航条(logo、导航栏、搜索框)
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/140268.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/01
5.8K0
html导航栏自动调间距,HTML CSS导航栏间距[通俗易懂]
我做了一个CSS导航栏,但是在每个“navbar-item”之间,都有一点空间。我不希望那里有任何变化!有没有办法做到这一点,而不改变每个navbar-item的余裕?HTML CSS导航栏间距
全栈程序员站长
2022/09/01
5.5K0
TabLayout用法,android顶部导航栏,android底部导航栏
TabLayout是android.support.design里的一个控件,使用它可以很方便的做出顶部导航和底部导航。类似于这样的,能设置选中时字体的颜色和选中时的图片。
天涯泪小武
2019/01/17
4.1K0
BootStrap 导航栏实现下滑消失,上滑出现
首先是导入bootstrap等样式,和jquery,再复制一个nav组件;代码如下:
多凡
2020/07/27
2K0
MCM数控机床切削颤振监测与大数据分析系统构建(一)
在金属切削加工过程中,刀具与工件之间剧烈的自激振动通常被称为“颤振”。机床颤振会使加工过程变得不稳定,造成加工表面质量和金属切削率的下降,引起加工工件的表面精度和光洁度下降,降低刀具使用寿命和生产率,严重时甚至会破坏刀具和机床。因此,颤振成为提高机床加工能力的最主要障碍。
SHOUT
2022/05/31
2.7K0
MCM数控机床切削颤振监测与大数据分析系统构建(一)
html页面缩小导航栏隐藏,html – 导航栏缩放问题[通俗易懂]
我有一个问题,我的导航栏似乎与CSS中的.container缩放.现在,我是一个新手,但我已经尝试搞乱CSS中的值,但无济于事.这是
全栈程序员站长
2022/09/02
4.6K0
bootstrap 导航栏 3
<!doctype html> <html> <head> <meta charset="utf-8"> <title>联想控股</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="css/bootstrap.css" rel="stylesheet" type="text/css"> <script src="http://code.jquery.com/jquery.js"></script> <script src="js/bootstrap.min.js"></script> </head> <body> <ul class="nav nav-tabs"> <li class="active"><a href="#">首页</a></li> <li><a href="#">个人设置</a></li> <li><a href="#">消息中心</a></li> </ul> </body> </html>
用户5760343
2019/07/05
2.1K0
视觉导航定位系统工作原理及过程
当今,由于数字图像处理和计算机视觉技术的迅速发展,越来越多的研究者采用摄像机作为全自主用移动机器人的感知传感器。这主要是因为原来的超声或红外传感器感知信息量有限,鲁棒性差,而视觉系统则可以弥补这些缺点。而现实世界是三维的,而投射于摄像镜头(CCD/CMOS)上的图像则是二维的,视觉处理的最终目的就是要从感知到的二维图像中提取有关的三维世界信息。
小白学视觉
2019/05/31
2.8K0
安卓10系统如何增加双导航栏
安卓系统默认支持一个导航栏和一个状态栏,有时客户需求双边按键或者三屏分开显示,例如左右显示按键中间为界面显示或者左边显示仪表盘中间显示导航界面右边显示车速时钟等,这种情况使用一个导航栏无法实现。
kaicer
2023/05/24
1.7K14
bootstrap nav导航栏
<nav class="navbar navbar-default" role="navigation"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="#">菜鸟教程</a> </div> <div> <ul class="nav navbar-nav"> <li class="active"><a href="#">iOS</a></li> <li><a href="#">SVN</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> Java <b class="caret"></b> </a> <ul class="dropdown-menu"> <li><a href="#">jmeter</a></li> <li><a href="#">EJB</a></li> <li><a href="#">Jasper Report</a></li> <li class="divider"></li> <li><a href="#">分离的链接</a></li> <li class="divider"></li> <li><a href="#">另一个分离的链接</a></li> </ul> </li> </ul> </div> </div> </nav>
用户5760343
2019/07/05
3.8K0
bootstrap nav导航栏
HTML导航栏制作
注释:加上 target=”_blank” 的话,点击有链接的文字,就会新打开一个标签页,若不加,则在本页面上直接打开链接网页。
全栈程序员站长
2022/09/01
4.8K0
点击加载更多

相似问题

颤振-透明系统导航栏

12

显示后导航器弹出开关条颤振

11

颤振系统导航栏和状态栏颜色

30

颤振滚动导航条

14

基于流的颤振开关条显示

61
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档