请考虑以下代码:
class Abase{};
class A1:public Abase{};
class A2:public A1{};
//etc
class Bbase{
public:
virtual void f(Abase* a);
virtual void f(A1* a);
virtual void f(A2* a);
};
class B1:public Bbase{
public:
void f(A1* a);
};
class B2:public Bbase{
public:
void f(A2* a);
};
int main(){
A1* a1=new A1();
A2* a2=new A2();
Bbase* b1=new B1();
Bbase* b2=new B2();
b1->f(a1); // calls B1::f(A1*), ok
b2->f(a2); // calls B2::f(A2*), ok
b2->f(a1); // calls Bbase::f(A1*), ok
b1->f(a2); // calls Bbase::f(A2*), no- want B1::f(A1*)!
}
Run Code Online (Sandbox Code Playgroud)
我很想知道为什么C++选择通过 …
C++ 03 $ 13.6/1-"[...]如果有一个用户编写的候选人具有与内置候选操作员函数相同的名称和参数类型,则内置操作符函数被隐藏,不包括在内在候选函数集中."
我不确定标准的引用意图.是否可以定义与内置运算符具有相同名称和类型的用户定义候选函数?
例如,下面显然是错误的.
int operator+(int)
Run Code Online (Sandbox Code Playgroud)
那么这句话是什么意思呢?
以下代码使用gcc和clang编译好.
template <typename T>
struct identity
{
typedef T type;
};
template <typename T>
void foo(typename identity<T>::type);
template <typename T>
void foo(T);
int main()
{
foo<int>(0);
}
Run Code Online (Sandbox Code Playgroud)
看起来重载决策是选择第一个重载(identity<T>::type一个).
有人可以解释为什么重载不是模棱两可的吗?据我所知,它们之间唯一的区别是第一个的参数是非推导的上下文而第二个的参数不是,但是因为我明确地提供了模板参数,所以我不赞成不明白为什么这很重要.
当用G ++(gcc 4.8.1和MinGW 4.8.2 with -std=gnu++1yflag)编译我的代码时,我发现了一个奇怪的行为.在SSCCE的精神中,我隔离了以下代码段:
struct C
{
template< typename X >
auto
f(X &&) const &
{ ; }
template< typename X >
auto
f(X &&) &
{ ; }
template< typename X >
auto
f(X &&) &&
{ ; }
};
int main()
{
int i{};
#if 1
C{}.f(i);
#endif
#if 1
C c{};
c.f(i);
#endif
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它给出了一个错误:
main.cpp: In function 'int main()':
main.cpp:29:10: error: call of overloaded …Run Code Online (Sandbox Code Playgroud) 我似乎不明白为什么你会使用move assignment operator:
CLASSA & operator=(CLASSA && other); //move assignment operator
Run Code Online (Sandbox Code Playgroud)
结束了copy assignment operator:
CLASSA & operator=(CLASSA other); //copy assignment operator
Run Code Online (Sandbox Code Playgroud)
在move assignment operator接受一个r-value reference只有如
CLASSA a1, a2, a3;
a1 = a2 + a3;
Run Code Online (Sandbox Code Playgroud)
在copy assignment operator,other可以是使用a copy constructor或a的构造函数move constructor(如果other用rvalue初始化,它可以是移动构造的 - 如果已move-constructor定义 - ).
如果是copy-constructed,我们将进行1份复制,并且无法避免该副本.
如果是,move-constructed那么性能/行为与第一次过载产生的性能/行为相同.
我的问题是:
1-为什么要实现move assignment operator.
2-如果 other是由r值构造的,那么assignment operator …
我正在尝试将Java 7代码迁移到Java 8,所以我的代码类似于:
package tests;
import java.util.Arrays;
import java.util.Map;
public class Tests {
private static interface ComparableMap<K,V> extends Map<K,V>, Comparable {}
public static void main(String[] args) {
func(getString());
}
private static void func(Comparable...input){
System.out.println(Arrays.toString(input));
}
private static void func(ComparableMap <?,?> m){
System.out.println(m);
}
private static <T extends Comparable> T getString(){
return (T) "aaa";
}
}
Run Code Online (Sandbox Code Playgroud)
在java 7中它正常工作,在Java 8中我得到:
java.lang.ClassCastException:java.lang.String无法强制转换为tests.Tests $ ComparableMap
如果我将一个函数定义更改为:
private static <T> T getString(){
return (T) "aaa";
}
Run Code Online (Sandbox Code Playgroud)
编译将失败:错误:
对func的引用含糊不清
为什么Java 8编译器在第一种情况下没有失败?(看起来对我来说是错误的)是否可以更改第二个重载函数,以便在不更改调用本身的情况下使用varargs参数调用第一个函数?
我有一个方法,我想在我的解决方案中采取所有类似列表的对象.在.NET 4.5之前,这很简单:
public static T Method<T>(IList<T> list)
{
// elided
}
Run Code Online (Sandbox Code Playgroud)
但是,.NET 4.5引入了IReadOnlyList<T>,这种方法也应该适用.
我不能只是改变签名来采取IReadOnlyList<T>,因为有些地方我将这种方法应用于特定类型的东西IList<T>.
该算法无法运行IEnumerable<T>,并且过于频繁地使用(并且对象太大)无法在每次调用时IEnumerable<T>创建新的算法List<T>.
我试过添加一个重载:
public static T Method<T>(IReadOnlyList<T> list)
{
// elided
}
Run Code Online (Sandbox Code Playgroud)
...但是这不会编译实现两个接口(T[],List<T>和许多其他类型)的任何东西,因为编译器无法确定使用哪种方法(特别烦人,因为它们具有相同的主体,所以它不会物).
我不希望有添加重载的Method内搭T[],以及List<T>和它实现了两个接口所有其他类型.
我该怎么做到这一点?
打印以下程序T,T。
#include <iostream>
template<typename T>
void f(T x, T y) {
std::cout << "T,T\n";
}
template<typename T1, typename T2>
void f(T1 x, T2 y) {
std::cout << "T1,T2\n";
}
int main() {
f(1, 1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
哪个模板在代码中排在第一位没有什么区别。
我希望重载解决方案在这里是模棱两可的。T,T1和T2都应推导为int,这使两个模板都与呼叫站点完全匹配。
我无法找到任何解析规则(https://en.cppreference.com/w/cpp/language/overload_resolution)来解释为什么它会选择第一个模板。
我测试了clang++ -std=c++17,以防万一。
在下面的程序中 structS提供了两个转换运算符: indouble和 in long long int。然后一个类型的对象S被传递给一个函数f,重载为floatand double:
struct S {
operator double() { return 3; }
operator long long int() { return 4; }
};
void f( double ) {}
void f( float ) {}
int main() {
S s;
f( s );
}
Run Code Online (Sandbox Code Playgroud)
MSVC 编译器可以正常接受程序,并选择f( double )重载。f然而,GCC 和 Clang 都发现, demo的调用存在歧义:https: //gcc.godbolt.org/z/5csd5dfYz
看来MSVC在这里是对的,因为转换:
operator long long int()->f( float )不是提升。这是错的吗? …
c++ overloading conversion-operator language-lawyer overload-resolution
我定义了两个版本的函数模板,名为compare:
#include <cstring>\n\nusing namespace std;\n\n// fist version\ntemplate <size_t N, size_t M>\nint compare(const char (&a)[N], const char (&b)[M]) {\n return strcmp(a, b);\n}\n\n// second version\ntemplate <typename T>\nint compare(const T &a, const T &b) {\n if (a < b) return -1;\n if (b < a) return 1;\n return 0;\n}\n\nint main() {\n const char *p1 = "dog", *p2 = "cat";\n compare(p1, p2); // call second version\n compare("dog", "cat"); // call second version?\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n在使用c++11std的CPP Primer(第5版)一书中,作者说compare(p1, p2)将调用第二版模板,因为没有办法将指针转换为对数组的引用。将 …