我被问到一个问题,我想在这里查看我的答案.
问:在哪种情况下扩展抽象类而不是实现接口更合适?
答:如果我们使用模板方法设计模式.
我对么 ?
如果我无法清楚地陈述问题,我很抱歉.
我知道抽象类和接口之间的基本区别.
1)当需求需要在特定操作的每个子类中实现相同的功能(实现方法)和其他一些操作的不同功能(仅方法签名)时,使用抽象类
2)如果需要将签名设置为相同(并且实现不同),请使用接口,以便您可以遵守接口实现
3)我们可以扩展一个抽象类的最大值,但可以实现多个接口
重申一个问题:除了上面提到的那些之外,还有其他任何场景,具体我们需要使用抽象类(一个是模板方法设计模式在概念上仅基于此)吗?
接口与抽象类
在这两者之间做出选择真的取决于你想做什么,但幸运的是,对我们来说,Erich Gamma可以帮助我们一点.
一如既往地存在权衡,接口为您提供基类的自由,抽象类使您可以自由地在以后添加新方法. - Erich Gamma
你无法在不改变代码中的许多其他东西的情况下更改接口,因此避免这种情况的唯一方法是创建一个全新的接口,这可能并不总是一件好事.
Abstract classes应主要用于密切相关的对象.Interfaces更好地为不相关的类提供通用功能.
当我尝试使用git gui(右键单击 - >用于提交的阶段行)来演示单行或多行时,我收到以下错误.这不是第一次发生在我身上,我发现其他人正面对它.但是我找不到如何解决它.
有没有人遇到过这个问题?有什么我可以做的(暂存所有文件不是一个真正的解决方案)
更新: 这是一个文件,当我尝试暂存已删除的行时,它给出了以下错误.
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/texture"
android:tileMode="repeat"
- android:dither="true"
>
</bitmap>
\ No newline at end of file
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
fatal: corrupt patch at line 14
Run Code Online (Sandbox Code Playgroud)
奇怪的是以下罚款甚至没有14行!?注意用新行结束文件并没有解决问题
我有一个项目,我正在使用Doxygen来生成文档.这些类的文档很好,但我也有一些函数,我在main()中使用它来创建对象等.我也想将这些函数放入我的文档中,但我还没有想到如何做到这一点.有什么建议?
我有这样的代码:
template<class ListItem>
static void printList(QList<ListItem>* list)
{
for (auto i = list->size() - 1, j = -1; i >= 0; --i) {
std::cout << i << ", " << j << ": " << list->at(i) << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
当我用g ++ 6.2.1编译它时,我得到以下编译器输出:
test.cpp: In function ‘void printList(QList<T>*)’:
test.cpp:10:7: error: inconsistent deduction for ‘auto’: ‘auto’ and then ‘int’
for (auto i = list->size() - 1, j = -1; i >= 0; --i) {
^~~~
Run Code Online (Sandbox Code Playgroud)
我理解这一点,如果变量有不同的类型auto i = 0.0, j …
g ++ 4.9.0接受以下代码:
enum E { foo };
struct C {
operator E() const { return foo; }
operator E() { return foo; }
};
int main() {
C c;
switch (c) {
case foo: break;
}
}
Run Code Online (Sandbox Code Playgroud)
但是clang 3.4.1通过以下诊断拒绝它:
12 : error: multiple conversions from switch condition type 'C' to an integral or enumeration type
switch (c)
^ ~
5 : note: conversion to enumeration type 'E'
operator E() const { return foo; }
^
6 : note: conversion …Run Code Online (Sandbox Code Playgroud) c++ switch-statement language-lawyer implicit-conversion c++11
标准(§14.1)模板参数说:
允许模板模板参数的模板参数具有默认模板参数.
现在考虑以下代码:
#include <iostream>
using namespace std;
struct A {};
struct B {};
template<typename T = A>
struct X;
template<>
struct X<A> {
static void f() { cout << 1 << endl; }
};
template<>
struct X<B> {
static void f() { cout << 2 << endl; }
};
template< template<typename T = B> class C>
void g() {
C<>::f();
}
int main() {
g<X>();
}
Run Code Online (Sandbox Code Playgroud)
它的输出是:
出局:2
在这种情况下,模板模板参数是C.
但我不明白为什么 C<B>::f()被称为内部g().
在Y::test1()非const X::operator void*()中优先于看似更好的匹配,X::operator bool() const- 为什么?标准中描述了这种现象在哪里?
#include <iostream>
struct X {
operator void*() { std::cout << " operator void*()\n"; return nullptr; }
operator bool() const { std::cout << " operator bool()\n"; return true; }
};
struct Y {
X x;
bool test1() { std::cout << "test1()\n"; return x; }
bool test2() const { std::cout << "test2()\n"; return x; }
};
int main() {
Y y;
y.test1();
y.test2();
}
Run Code Online (Sandbox Code Playgroud)
输出:
test1()
operator void*()
test2()
operator bool()
Run Code Online (Sandbox Code Playgroud) 考虑这段代码,它使用具有函数模板的常用习惯用法构造专门用于推导类型的类模板的实例,如std::make_unique和std::make_tuple以下所示:
template <typename T>
struct foo
{
std::decay_t<T> v_;
foo(T&& v) : v_(std::forward<T>(v)) {}
};
template <typename U>
foo<U> make_foo(U&& v)
{
return { std::forward<U>(v) };
}
Run Code Online (Sandbox Code Playgroud)
在斯科特迈尔斯'通用引用’的上下文中,所述参数
make_foo是一个普遍的基准,因为它的类型是U&&其中U推导出.到的构造函数的参数foo不是通用参考,因为尽管其类型为T&&,T是(通常)不能推导出.
但是在foo调用构造函数的情况下,在make_foo我看来,将构造函数的参数foo看作是一个通用引用可能是有意义的,因为T它是由函数模板推导出来的make_foo.将应用相同的参考折叠规则,以便v两个函数中的类型相同.在这种情况下,无论是T
和U可以说已经推出.
所以我的问题是双重的:
foo在有限的情况下,将构造函数的参数视为通用引用是否有意义T,在调用者的通用引用上下文中,如在我的示例中那样?std::forward明智的用途吗?c++ language-lawyer perfect-forwarding c++11 universal-reference
在我的应用程序中,我有以下类层次结构:
class Word
{
...
}
template <typename T> class Dictionary
{
...
};
class WordDictionary : public Dictionary<Word>
{
Q_OBJECT
...
}
Run Code Online (Sandbox Code Playgroud)
WordDictionary类解析需要很长时间的字典.我正在一个单独的线程中运行解析函数,我希望它能够不时地通知GUI线程,以根据正在解析的当前行号提供进度更新.这就是我希望它成为Q_OBJECT的原因.我试图使基类Dictionary成为Q_OBJECT,但得到的消息是不支持Q_OBJECT模板.当我删除宏,只留下WordDictionary作为Q_OBJECT时,我得到一堆一般形式的错误消息:
\ GeneratedFiles \发布\ moc_dictionary.cpp(44):错误C2039: 'staticMetaObject':不是'词典'中的一员
与
[
T =字
]
有什么办法可以让我的模板派生的WordDictionary类成为Q_OBJECT而不是硬编码里面的模板函数,产生了很多样板代码吗?
编辑:将模板声明更改为:
template <typename T> class Dictionary : public QObject
Run Code Online (Sandbox Code Playgroud)
使代码编译.我不确定我是不是做了一些愚蠢的事情,如果能够正常工作的话.
考虑一下简单的C++ 11代码:
template<int N>
struct Foo {};
template <int N>
constexpr int size(const Foo<N>&) { return N; }
template <int N>
void use_size(const Foo<N>& foo) { constexpr int n = size(foo); }
int main()
{
Foo<5> foo;
constexpr int x = size(foo); // works with gcc and clang
// _but_
use_size(foo); // the same statement in the use_size()
// function _only_ works for gcc
}
Run Code Online (Sandbox Code Playgroud)
我可以成功地编译它 g++ -std=c++11 foo.cpp
但是,如果我使用clang ++,clang++ -std=c++11 foo.cpp我会得到
foo.cpp:15:28: error: constexpr variable 'n' …Run Code Online (Sandbox Code Playgroud)