如何创建使用重写函数的非成员函数?

时间:2016-12-31 09:22:32

标签: c++ oop operators

在这段代码中我尝试基本上重载+ =操作。在非成员部分中一切看起来都没问题,但是当我写一个非成员函数时,(+部分中的操作)它给出了无效的抽象返回类型错误并且说 + =操作是纯粹的vector1d 即可。我该如何解决这个问题?

import React, { PropTypes } from 'react'

import map                  from "lodash/map"
import $                    from 'jquery';

import "../../app/assets/vendors/select2/dist/js/select2.full.min.js"
class SingleSelect extends React.Component{

  componentDidMount() {
    $(this.refs.singleselect).select2({
        placeholder: this.props.placeholder
    });
  }

  changed(){console.log("Changed")}

  render () {
    const taged_options = map(this.props.options, (val, key) =>
                <option key={ key } value={val}>{val} </option>
    )

    return (
      <div className="form-group">
        <label className="control-label col-md-3 col-sm-3 col-xs-12">
          {this.props.label}
        </label>
        <div className="col-md-8 col-sm-6 col-xs-12">
          <select
            onChange={this.changed}
            ref="singleselect"
            className="form-control"
            value="Wholesaler"
            name={this.props.name}
          >
            {taged_options}
          </select>
        </div>
      </div>
    )
  }
}

SingleSelect.propTypes = {
  label: React.PropTypes.string.isRequired,
  placeholder: React.PropTypes.string.isRequired,
  required: React.PropTypes.bool.isRequired,
  options: React.PropTypes.object.isRequired,
}

SingleSelect.defaultProps = {
  placeholder: "Select a value from list"
};

export default SingleSelect

3 个答案:

答案 0 :(得分:5)

覆盖时使用C ++ 11 override上下文关键字。这会使你的错误更接近你犯错的地方。这是你没有覆盖的。

你在其他地方被告知,但这很令人困惑。

此:

virtual AbstractBase &operator+=(const AbstractBase &other)=0;

与此签名不同:

Vector1d &operator+=(const Vector1d &other);

第二个不会覆盖第一个。它只是超载。 (他们是不同的!)

您还违反了LSP(see here),这基本上表明您的设计存在根本性错误。我缺乏有关如何解决该问题的信息。 LSP违规不会导致构建中断。

要修复构建中断,只需执行以下操作:

Vector1d &operator+=(const AbstractBase &other) override; // and maybe final

(返回类型不完全匹配;这是正常的,override关键字检查它,因为C ++中的协变返回类型规则。协方差不适用于const&参数(也就是说)在任何明智的语言中(逆向可能是明智的,但C ++不会免费提供,并且你无论如何都不会这样做。)

对于身体:

Vector1d &Vector1d::operator+=(const AbstractBase &other_abstract){
    auto& other = dynamic_cast<Vector1d const&>(other_abstract); // can throw
    std::cout<<"sum operator is called"<<std::endl;
    for(int i = 0; i < other.size_ ; i++)
      data_.at(i) += other.data_.at(i);
    return *this;
}

如果抽象类型与您期望的类型不匹配,则现在抛出错误的强制转换。这是可怕的,但它建立。

LSP错误是您的抽象基础+=暗示具有相同抽象基数的任何两个对象可以是+='d。你的实施并不一致,非常合理。这意味着你的班级heirarchy是垃圾,应该被扔掉,可能不会被替换。但这是一个比我在技术构建中断的答案中所能涵盖的更广泛的问题。

答案 1 :(得分:4)

从根本上说,你永远不会覆盖operator+=(const AbstractBase &other)

您提供的新operator+=需要const Vector1d&,但这只允许+=使用派生类型。

基类操作符+=可以与任何AbstractBase一起使用,因此当您覆盖它时,您需要保留签名,以便派生的实现也适用于任何AbstractBase。 / p>

这可能对你的班级层次没有意义,所以要仔细考虑抽象基类的效用&#39; operator+=

答案 2 :(得分:3)

即使Vector1d继承自AbstractBase

Vector1d &operator+=(const Vector1d &other);

的签名不同

AbstractBase &operator+=(const AbstractBase &other)=0

因此,它不能成为覆盖的候选者。