1樓:Lee Revere
CRTP 可以
template
T>class Iterator ;class Derived ;template <>class Iterator >};class Derived :public Iterator >{};begin() and end() template >class Base ;class Derived ;template >class Iter ;// 對於每乙個子類都定義乙個基類。 template <>class Base >;Iter >end() };class Derived :public Base >; 2樓: 無解。這麼寫會有問題。 Iter* it = rand() ? new MyIter() : new YourIter(); auto ret = it->operator++(114514); // what type of ret??? 這不是抽象類不能做返回型別的問題,只要是虛函式,返回型別必須是一樣的(協變的)。只有宣告成 Iter* operator++(int) ,然後子類 MyIter* operator++(int) 才能解決型別衝突問題,這樣 it->operator++(1926817) 就算呼叫子類的 operator++ ,返回型別也一定是父類的 Iter* 。 如果返回型別不能協變的話,這就是無解的。 有人提到 CRTP ,確實可以解決型別問題,但是沒什麼用。如果抽象類是模板的話,難道你的介面要設計成這樣麼: template void f(Iter* it); 那我還不如用 concept : template void f(T* it);算了。 3樓:傳統的幻想書屋 你的子類的Iter跟父類的Iter沒有半毛錢關係,返回值都不一樣了,你這裡的Iterator更像是乙個要求可迭代的介面約束。不需要動態繫結的話,其實不需要繼承基類。你只需要乙個約束就可以了,可以使用concept,沒有concept支援的話,使用現有的type traits工具也能做,不過比較難看。 貼乙個用Concept實現的簡易demo。 #include #include #include #include template T>concept Range =requires(T t)->std:: same_as .end ())> ;//兩個函式返回值型別要一樣 };//實際上還要約束返回值是一種迭代器,這裡省略了 //定義三個類,實現情況如下 struct Container1 intend ()}; struct Container2 };struct Container3 intend ()const };//要求乙個滿足Range要求的型別Iter template Iter >void func (const Iter&c )int main (int argc ,char const *argv )/Users/li/CLionProjects/test/main.cpp: In function 'int main(int, const char**)': /Users/li/CLionProjects/test/main.cpp:86: 12: error: use of function 'void func(const Iter&) [with Iter = Container1]' with unsatisfied constraints 86 | func(c1Users/li/CLionProjects/test/main.cpp:28:6: note: declared here 28 | void func(const Iter& cUsers/li/CLionProjects/test/main.cpp:28: 6: note: constraints not satisfied /Users/li/CLionProjects/test/main.cpp: In instantiation of 'void func(const Iter&) [with Iter = Container1]': /Users/li/CLionProjects/test/main.cpp:86:12: required from here /Users/li/CLionProjects/test/main.cpp:6: 9: required for the satisfaction of 'Range' [with Iter = Container1] /Users/li/CLionProjects/test/main.cpp:6: 17: in requirements with 'T t' [with T = Container1] /Users/li/CLionProjects/test/main.cpp:10: 13: note: 't. begin()' does not satisfy return-type-requirement 10 | ->std::same_as; //對於Container1型別,這裡不滿足begin和end返回值相同的要求,報錯cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail /Users/li/CLionProjects/test/main.cpp:87: 12: error: use of function 'void func(const Iter&) [with Iter = Container2]' with unsatisfied constraints 87 | func(c2Users/li/CLionProjects/test/main.cpp:28:6: note: declared here 28 | void func(const Iter& cUsers/li/CLionProjects/test/main.cpp:28: 6: note: constraints not satisfied /Users/li/CLionProjects/test/main.cpp: In instantiation of 'void func(const Iter&) [with Iter = Container2]': /Users/li/CLionProjects/test/main.cpp:87:12: required from here /Users/li/CLionProjects/test/main.cpp:6: 9: required for the satisfaction of 'Range' [with Iter = Container2] /Users/li/CLionProjects/test/main.cpp:6: 17: in requirements with 'T t' [with T = Container2] /Users/li/CLionProjects/test/main.cpp:9: 10: note: the required expression 't. end()' is invalid 9 | t.end();//對於Container2型別,這裡不滿足擁有乙個叫end的成員函式,也報錯Users/li/CLionProjects/test/main.cpp: 10:13: note: 't.begin()' does not satisfy return-type-requirement 10 | ->std::same_asfunc(c3)呼叫沒有報錯,因為其完全符合Range的概念要求 如果你要求乙個可迭代的物件,那麼也可以實現 template concept ForwardIterator=requires(T i,T jvoid)iii!=ji要求過載了前後置自增,比較,解引用運算子 template concept BackwardIterator=requires(T i,T j) ; //同上 //標準庫里有類似的Concept,不過比這個約束要更全面一些,比如約束*運算子必須返回引用之類的。 template requires requires(Iter it) //要求滿足ForwardIterator 並且其解引用的結果可以使用cout列印 void Test(Iter first,Iter last) template requires requires(Iter it) //要求滿足BackwardIterator 並且其解引用的結果可以使用cout列印 void Test(Iter first,Iter last) int main(int argc, char const *argvstd::forward_list intList; std::forward_list containerList,,,,};//這是Container1是第乙個測試裡那個型別 Test(intList.begin(),intList.end());//編譯通過 Test(containerList.begin(),containerList.end());//編譯報錯 return 0; } 執行上面的測試,第二個Test函式沒注釋掉,編譯器報錯 /Users/li/CLionProjects/test/main.cpp:53: 38: note: the required expression '(std:: cout << (* it))' is invalid 53 | requires requires(Iter it) Container1沒過載<<,無法通過cout列印編譯不通過。注釋掉第二個Test函式,編譯通過。 執行程式,列印結果,可以看到呼叫的正是第乙個要求ForwardIterator的函式,因為std::forward_list是單鏈表,其迭代器只能自增,不能自減,只能匹配第乙個Test函式。 ForwardIterator 1 2 3 4 5 Process finished with exit code 0 然後就是你的需求了。你想要乙個約束,要求滿足約束的類必須有乙個begin函式,返回其自己的迭代器型別物件,然後這個迭代器型別又必須滿足能夠自增的約束。 #include #include #include template concept Iterator=requires (T tt; };//Iterator約束要求實現operator++(int) template concept Base = requires(std::add_const_t t)//要求begin必須是const成員函式 ->Iterator; };//要求Base約束的型別,有個begin函式,且返回值滿足Iterator約束 struct ImplClass1;} };//可以選擇返回任意型別,只要滿足Iterator約束,這裡int是滿足的,但是std::vector不滿足,所以後面編譯報錯 struct ImplClass3; template void test(const T& t) int main(int argc, char const *argvImplClass1 i1; ImplClass2 i2; ImplClass3 i3; test(i1); test(i2); test(i3); return 0; }後兩個test報錯 /Users/li/CLionProjects/test/main.cpp: In function 'int main(int, const char**)': /Users/li/CLionProjects/test/main.cpp:44: 12: error: use of function 'void test(const T&) [with T = ImplClass2]' with unsatisfied constraints 44 | test(i2Users/li/CLionProjects/test/main.cpp:32:6: note: declared here 32 | void test(const T& tUsers/li/CLionProjects/test/main.cpp:32: 6: note: constraints not satisfied /Users/li/CLionProjects/test/main.cpp: In instantiation of 'void test(const T&) [with T = ImplClass2]': /Users/li/CLionProjects/test/main.cpp:44:12: required from here /Users/li/CLionProjects/test/main.cpp:14: 9: required for the satisfaction of 'Base' [with T = ImplClass2] /Users/li/CLionProjects/test/main.cpp:14: 16: in requirements with 'std::add_const_t t' [with _Tp = ImplClass2; T = ImplClass2] /Users/li/CLionProjects/test/main.cpp:16: 13: note: 't. begin()' does not satisfy return-type-requirement 16 | ->Iterator; //返回值std::vector沒有++過載運算子,不滿足Iterator約束,報錯cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail /Users/li/CLionProjects/test/main.cpp:45: 12: error: use of function 'void test(const T&) [with T = ImplClass3]' with unsatisfied constraints 45 | test(i3Users/li/CLionProjects/test/main.cpp:32:6: note: declared here 32 | void test(const T& tUsers/li/CLionProjects/test/main.cpp:32: 6: note: constraints not satisfied /Users/li/CLionProjects/test/main.cpp: In instantiation of 'void test(const T&) [with T = ImplClass3]': /Users/li/CLionProjects/test/main.cpp:45:12: required from here /Users/li/CLionProjects/test/main.cpp:14: 9: required for the satisfaction of 'Base' [with T = ImplClass3] /Users/li/CLionProjects/test/main.cpp:14: 16: in requirements with 'std::add_const_t t' [with _Tp = ImplClass3; T = ImplClass3] /Users/li/CLionProjects/test/main.cpp:16: 13: note: the required expression 't. begin()' is invalid 16 | ->Iterator; //沒有begin函式,報錯 c++20之前沒有概念,寫這個東西非常麻煩,報錯不是人看的,有了概念就能很方便的進行泛型約束了,用於編譯期多型,要執行期多型還是要虛函式。可以兩者根據需求結合使用,非常強大。 悽臨雨 無捕獲的lambda,可以轉型為c函式指標。類內巢狀類可以定義靜態函式 不一定合乎要求 但據我所知都只能獲取指標,沒辦法定義c函式 因為c函式應當處在c的命名空間中 陸海綿 使用函式指標成員指向乙個類外定義的C函式。extern c class Avoid p int 實在想不到哪種應用場景... 張浩 永遠都應該寫成int main void 或者int main int argc,char argv void main?不知道從哪傳出來的寫法 穀雨同學 無論如何,使用void作為返回值型別的main函式都是不符合標準的。請在任何情況下都避免這樣寫。但是main函式可以不寫return語句,... 小明 別總想著只要是物件就要new,多用RAII解決資源問題。首先你的linklist初始化就不要new.你要做的是過載 operator 接著linklist繼承的是linerlist是如何實現,為啥抽象基類要具體化,你只是使用他的指標。多用智慧型指標,如果嫌棄智慧型指標,就學一下智慧型指標的思路...C 如何在類中定義乙個 C 函式(不用傳遞 this,非友元,非靜態)?
c語言如何定義沒有返回值的main函式
C 抽象類作為模板引數,當其為指標時,如何析構?