我已经教了很多年的C++编程课程,向学生解释的最棘手的事情之一是const重载.我通常使用类似矢量的类及其operator[]函数的示例:
template <typename T> class Vector {
public:
T& operator[] (size_t index);
const T& operator[] (size_t index) const;
};
Run Code Online (Sandbox Code Playgroud)
我很难解释为什么需要两个版本的operator[]函数,但在试图解释如何将两个实现统一起来时,我常常发现自己浪费了很多时间使用语言arcana.问题是,我知道如何使用const_cast/ static_casttrick 实现其中一个函数的唯一好的,可靠的方法是:/ trick:
template <typename T> const T& Vector<T>::operator[] (size_t index) const {
/* ... your implementation here ... */
}
template <typename T> T& Vector<T>::operator[] (size_t index) {
return const_cast<T&>(static_cast<const Vector&>(*this)[index]);
}
Run Code Online (Sandbox Code Playgroud)
这种设置的问题在于解释起来非常棘手,而且根本不明显.当你把它解释为"转换为const,然后调用const版本,然后去掉constness"时,它会更容易理解,但实际的语法是可怕的.解释什么const_cast是,为什么它的适当位置,以及它为什么几乎普遍不恰当的其他地方通常需要我五至十分钟的演讲时间,而这整个表达式的决策意识往往需要比之间的差异更多的精力const T*和T* const.我觉得学生需要了解const-overloading以及如何在不必要地复制两个函数中的代码的情况下完成它,但是这个技巧在C++入门编程课程中似乎有些过分.
我的问题是 - 是否有一种更简单的方法来实现相互const重叠的功能?或者是否有更简单的方法向学生解释现有技巧?
这可能是一个noob问题,抱歉.我最近遇到了一个奇怪的问题,试图在c ++,函数重载和继承中搞乱一些高级的东西.
我将展示一个简单的例子,只是为了证明这个问题;
有两个班,classA和classB如下;
class classA{
public:
void func(char[]){};
};
class classB:public classA{
public:
void func(int){};
};
Run Code Online (Sandbox Code Playgroud)
据我所知classB,现在应该拥有两个func(..)函数,由于参数不同而重载.
但是在主方法中尝试这个时;
int main(){
int a;
char b[20];
classB objB;
objB.func(a); //this one is fine
objB.func(b); //here's the problem!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它给出了错误,因为void func(char[]){}; 超类中的方法classA在派生类中是不可见的classB.
我怎么能克服这个?这不是在c ++中如何重载?我是c ++的新手,但在Java中,我知道我可以使用这样的东西.
我有一个处理给定向量的函数,但如果没有给出,也可以自己创建这样的向量.
我看到这种情况有两种设计选择,其中一个函数参数是可选的:
将它设为指针并NULL默认设置为:
void foo(int i, std::vector<int>* optional = NULL) {
if(optional == NULL){
optional = new std::vector<int>();
// fill vector with data
}
// process vector
}
Run Code Online (Sandbox Code Playgroud)
或者有两个带有重载名称的函数,其中一个省略了参数:
void foo(int i) {
std::vector<int> vec;
// fill vec with data
foo(i, vec);
}
void foo(int i, const std::vector<int>& optional) {
// process vector
}
Run Code Online (Sandbox Code Playgroud)
是否有理由选择一种解决方案而不是另一种?
我稍微偏爱第二个,因为我可以将向量作为const引用,因为它在提供时只能读取而不能写入.此外,界面看起来更干净(NULL不仅仅是一个黑客?).并且间接函数调用产生的性能差异可能会被优化掉.
然而,我经常在代码中看到第一个解决方案.除了程序员的懒惰之外,是否有令人信服的理由更喜欢它?
如何做这项工作?如何实现C99/C++ 11可变参数宏以根据给出多少参数来扩展到不同的东西?
#include <iostream>
using namespace std;
template<typename T>
void f(T&&) { cout << "f(T&&)" << endl; }
template<typename T>
void f(const T&&) { cout << "f(const T&&)" << endl; }
struct A {};
const A g1() { return {}; }
const int g2() { return {}; }
int main()
{
f(g1()); // outputs "f(const T&&)" as expected.
f(g2()); // outputs "f(T&&)" not as expected.
}
Run Code Online (Sandbox Code Playgroud)
问题描述嵌入在代码中.我的编译器是clang 5.0.
我只是好奇:
在这种情况下,为什么C++会以不同方式处理内置类型和自定义类型?
在C++ 17中,实现一个overload(fs...)函数是很容易的,在fs...满足任意数量的参数的情况下FunctionObject,它返回一个行为类似于重载的新函数对象fs....例:
template <typename... Ts>
struct overloader : Ts...
{
template <typename... TArgs>
overloader(TArgs&&... xs) : Ts{forward<TArgs>(xs)}...
{
}
using Ts::operator()...;
};
template <typename... Ts>
auto overload(Ts&&... xs)
{
return overloader<decay_t<Ts>...>{forward<Ts>(xs)...};
}
int main()
{
auto o = overload([](char){ cout << "CHAR"; },
[](int) { cout << "INT"; });
o('a'); // prints "CHAR"
o(0); // prints "INT"
}
Run Code Online (Sandbox Code Playgroud)
由于上面的overloader继承Ts...,它需要复制或移动函数对象才能工作.我想要一些提供相同重载行为的东西,但只引用传递的函数对象.
我们称之为假设函数ref_overload(fs...).我的尝试正在使用std::reference_wrapper …
c++ overloading function-object template-meta-programming c++17
我只是看着番石榴ImmutableList,我注意到这个of()方法超载了12次.
在我看来,他们所需要的只是:
static <E> ImmutableList<E> of();
static <E> ImmutableList<E> of(E element); // not even necessary
static <E> ImmutableList<E> of(E... elements);
Run Code Online (Sandbox Code Playgroud)
有这么多类似变化的原因是什么?
在定义使用不同过滤器返回相同形状数据的多个方法时,有什么更好的做法?显式方法名称或重载方法?
例如.如果我有一些产品,我从数据库中提取
明确的方式:
public List<Product> GetProduct(int productId) { // return a List }
public List<Product> GetProductByCategory(Category category) { // return a List }
public List<Product> GetProductByName(string Name ) { // return a List }
Run Code Online (Sandbox Code Playgroud)
重载方式:
public List<Product> GetProducts() { // return a List of all products }
public List<Product> GetProducts(Category category) { // return a List by Category }
public List<Product> GetProducts(string searchString ) { // return a List by search string }
Run Code Online (Sandbox Code Playgroud)
我意识到你可能会遇到类似签名的问题,但是如果你传递的是对象而不是基类型(string,int,char,DateTime等),这将不再是一个问题.所以...是一个好主意,重载的方法来减少你有方法和清晰的数字,或者应该 …
在我正在研究的PHP Web应用程序中,我看到以两种可能的方式定义函数.
方法1:
function myfunc($arg1, $arg2, $arg3)
Run Code Online (Sandbox Code Playgroud)
方法2:
// where $array_params has the structure array('arg1'=>$val1, 'arg2'=>$val2, 'arg3'=>$val3)
function myfunc($array_params)
Run Code Online (Sandbox Code Playgroud)
什么时候应该使用一种方法而不是另一种 似乎如果系统要求不断变化,因此myfunc的参数数量不断变化,方法1可能需要大量维护.
public class A {
public void f1(String str) {
System.out.println("A.f1(String)");
this.f1(1, str);
}
public void f1(int i, String str) {
System.out.println("A.f1(int, String)");
}
}
public class B extends A {
@Override
public void f1(String str) {
System.out.println("B.f1(String)");
super.f1(str);
}
@Override
public void f1(int i, String str) {
System.out.println("B.f1(int, String)");
super.f1(i, str);
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.f1("Hello");
}
}
Run Code Online (Sandbox Code Playgroud)
我正在寻求这段代码输出:
B.f1(String)
A.f1(String)
A.f1(int, String)
Run Code Online (Sandbox Code Playgroud)
但我得到了:
B.f1(String)
A.f1(String)
B.f1(int, …Run Code Online (Sandbox Code Playgroud)